text: "use strict";(self.webpackChunkjjbook=self.webpackChunkjjbook||[]).push([[1440],{3905:function(e,t,n){n.d(t,{Zo:function(){return u},kt:function(){return d}});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?r(Object(n),!0).forEach((function(t){a(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):r(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function l(e,t){if(null==e)return{};var n,o,a=function(e,t){if(null==e)return{};var n,o,a={},r=Object.keys(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o<r.length;o++)n=r[o],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),c=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=c(e.components);return o.createElement(s.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},k=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),k=c(n),d=a,m=k["".concat(s,".").concat(d)]||k[d]||p[d]||r;return n?o.createElement(m,i(i({ref:t},u),{},{components:n})):o.createElement(m,i({ref:t},u))}));function d(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=k;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,i[1]=l;for(var c=2;c<r;c++)i[c]=n[c];return o.createElement.apply(null,i)}return o.createElement.apply(null,n)}k.displayName="MDXCreateElement"},2158:function(e,t,n){n.r(t),n.d(t,{frontMatter:function(){return l},contentTitle:function(){return s},metadata:function(){return c},toc:function(){return u},default:function(){return k}});var o=n(7462),a=n(3366),r=(n(7294),n(3905)),i=["components"],l={sidebar_label:"\u6846\u67b6\uff1aReact Hooks \u5b9e\u73b0\u539f\u7406",sidebar_position:4},s="React Hooks \u5b9e\u73b0\u539f\u7406",c={unversionedId:"book3/frame-react-hooks",id:"book3/frame-react-hooks",isDocsHomePage:!1,title:"React Hooks \u5b9e\u73b0\u539f\u7406",description:"\u76f8\u5173\u95ee\u9898",source:"@site/docs/book3/frame-react-hooks.md",sourceDirName:"book3",slug:"/book3/frame-react-hooks",permalink:"/awesome-interview/book3/frame-react-hooks",tags:[],version:"current",sidebarPosition:4,frontMatter:{sidebar_label:"\u6846\u67b6\uff1aReact Hooks \u5b9e\u73b0\u539f\u7406",sidebar_position:4},sidebar:"tutorialSidebar",previous:{title:"\u5de5\u7a0b\u5316\uff1a\u8c08\u4e0b webpack loader \u7684\u673a\u5236",permalink:"/awesome-interview/book3/engineer-webpack-loader"},next:{title:"\u6846\u67b6\uff1a\u5e38\u89c1\u6846\u67b6\u7684 Diff \u7b97\u6cd5",permalink:"/awesome-interview/book3/frame-diff"}},u=[{value:"\u76f8\u5173\u95ee\u9898",id:"\u76f8\u5173\u95ee\u9898",children:[]},{value:"\u56de\u7b54\u5173\u952e\u70b9",id:"\u56de\u7b54\u5173\u952e\u70b9",children:[]},{value:"\u77e5\u8bc6\u70b9\u6df1\u5165",id:"\u77e5\u8bc6\u70b9\u6df1\u5165",children:[{value:"1. \u7b80\u5316\u5b9e\u73b0",id:"1-\u7b80\u5316\u5b9e\u73b0",children:[]},{value:"2. \u5bf9\u6bd4\u5206\u6790",id:"2-\u5bf9\u6bd4\u5206\u6790",children:[]},{value:"3. Hooks \u5982\u4f55\u4e0e Fiber \u5171\u540c\u5de5\u4f5c",id:"3-hooks-\u5982\u4f55\u4e0e-fiber-\u5171\u540c\u5de5\u4f5c",children:[]}]},{value:"\u53c2\u8003\u8d44\u6599",id:"\u53c2\u8003\u8d44\u6599",children:[]}],p={toc:u};function k(e){var t=e.components,n=(0,a.Z)(e,i);return(0,r.kt)("wrapper",(0,o.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h1",{id:"react-hooks-\u5b9e\u73b0\u539f\u7406"},"React Hooks \u5b9e\u73b0\u539f\u7406"),(0,r.kt)("h2",{id:"\u76f8\u5173\u95ee\u9898"},"\u76f8\u5173\u95ee\u9898"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"React Hooks \u662f\u4ec0\u4e48"),(0,r.kt)("li",{parentName:"ul"},"React Hooks \u662f\u600e\u4e48\u5b9e\u73b0\u7684"),(0,r.kt)("li",{parentName:"ul"},"\u4f7f\u7528 React Hooks \u9700\u8981\u6ce8\u610f\u4ec0\u4e48")),(0,r.kt)("h2",{id:"\u56de\u7b54\u5173\u952e\u70b9"},"\u56de\u7b54\u5173\u952e\u70b9"),(0,r.kt)("p",null,(0,r.kt)("inlineCode",{parentName:"p"},"\u95ed\u5305")," ",(0,r.kt)("inlineCode",{parentName:"p"},"Fiber")," ",(0,r.kt)("inlineCode",{parentName:"p"},"\u94fe\u8868")),(0,r.kt)("p",null,"Hooks \u662f React 16.8 \u7684\u65b0\u589e\u7279\u6027\u3002\u5b83\u53ef\u4ee5\u8ba9\u4f60\u5728\u4e0d\u7f16\u5199 class \u7684\u60c5\u51b5\u4e0b\u4f7f\u7528 state \u4ee5\u53ca\u5176\u4ed6\u7684 React \u7279\u6027\u3002"),(0,r.kt)("p",null,"Hooks \u4e3b\u8981\u662f\u5229\u7528\u95ed\u5305\u6765\u4fdd\u5b58\u72b6\u6001\uff0c\u4f7f\u7528\u94fe\u8868\u4fdd\u5b58\u4e00\u7cfb\u5217 Hooks\uff0c\u5c06\u94fe\u8868\u4e2d\u7684\u7b2c\u4e00\u4e2a Hook \u4e0e Fiber \u5173\u8054\u3002\u5728 Fiber \u6811\u66f4\u65b0\u65f6\uff0c\u5c31\u80fd\u4ece Hooks \u4e2d\u8ba1\u7b97\u51fa\u6700\u7ec8\u8f93\u51fa\u7684\u72b6\u6001\u548c\u6267\u884c\u76f8\u5173\u7684\u526f\u4f5c\u7528\u3002"),(0,r.kt)("p",null,"\u4f7f\u7528 Hooks \u7684\u6ce8\u610f\u4e8b\u9879\uff1a"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u4e0d\u8981\u5728\u5faa\u73af\uff0c\u6761\u4ef6\u6216\u5d4c\u5957\u51fd\u6570\u4e2d\u8c03\u7528 Hooks\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u53ea\u5728 React \u51fd\u6570\u4e2d\u8c03\u7528 Hooks\u3002")),(0,r.kt)("h2",{id:"\u77e5\u8bc6\u70b9\u6df1\u5165"},"\u77e5\u8bc6\u70b9\u6df1\u5165"),(0,r.kt)("h3",{id:"1-\u7b80\u5316\u5b9e\u73b0"},"1. \u7b80\u5316\u5b9e\u73b0"),(0,r.kt)("p",null,(0,r.kt)("a",{parentName:"p",href:"https://codesandbox.io/s/hopeful-williams-id7ey?file=/src/index.js"},"React Hooks \u6a21\u62df\u5b9e\u73b0")),(0,r.kt)("p",null,"\u8be5\u793a\u4f8b\u662f\u4e00\u4e2a React Hooks \u63a5\u53e3\u7684\u7b80\u5316\u6a21\u62df\u5b9e\u73b0\uff0c\u53ef\u4ee5\u5b9e\u9645\u8fd0\u884c\u89c2\u5bdf\u3002\u5176\u4e2d ",(0,r.kt)("inlineCode",{parentName:"p"},"react.js")," \u6587\u4ef6\u6a21\u62df\u5b9e\u73b0\u4e86 ",(0,r.kt)("inlineCode",{parentName:"p"},"useState")," \u548c ",(0,r.kt)("inlineCode",{parentName:"p"},"useEffect")," \u63a5\u53e3\uff0c\u5176\u57fa\u672c\u539f\u7406\u548c react \u5b9e\u9645\u5b9e\u73b0\u7c7b\u4f3c\u3002"),(0,r.kt)("h3",{id:"2-\u5bf9\u6bd4\u5206\u6790"},"2. \u5bf9\u6bd4\u5206\u6790"),(0,r.kt)("h4",{id:"21-\u72b6\u6001-hook"},"2.1 \u72b6\u6001 Hook"),(0,r.kt)("p",null,"\u6a21\u62df\u7684 useState \u5b9e\u73b0\u4e2d\uff0c\u901a\u8fc7\u95ed\u5305\uff0c\u5c06 state \u4fdd\u5b58\u5728 ",(0,r.kt)("inlineCode",{parentName:"p"},"memoizedState[cursor]"),"\u3002 memoizedState \u662f\u4e00\u4e2a\u6570\u7ec4\uff0c\u53ef\u4ee5\u6309\u987a\u5e8f\u4fdd\u5b58 hook \u591a\u6b21\u8c03\u7528\u4ea7\u751f\u7684\u72b6\u6001\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"let memoizedState = [];\nlet cursor = 0;\nfunction useState(initialValue) {\n  // \u521d\u6b21\u8c03\u7528\u65f6\uff0c\u4f20\u5165\u7684\u521d\u59cb\u503c\u4f5c\u4e3a state\uff0c\u540e\u7eed\u4f7f\u7528\u95ed\u5305\u4e2d\u4fdd\u5b58\u7684 state\n  let state = memoizedState[cursor] ?? initialValue;\n  // \u5bf9\u6e38\u6807\u8fdb\u884c\u95ed\u5305\u7f13\u5b58\uff0c\u4f7f\u5f97 setState \u8c03\u7528\u65f6\uff0c\u64cd\u4f5c\u6b63\u786e\u7684\u5bf9\u5e94\u72b6\u6001\n  const _cursor = cursor;\n  const setState = (newValue) => (memoizedState[_cursor] = newValue);\n  // \u6e38\u6807\u81ea\u589e\uff0c\u4e3a\u63a5\u4e0b\u6765\u8c03\u7528\u7684 hook \u4f7f\u7528\u65f6\uff0c\u5f15\u7528 memoizedState \u4e2d\u7684\u65b0\u4f4d\u7f6e\n  cursor += 1;\n  return [state, setState];\n}\n")),(0,r.kt)("p",null,"\u5b9e\u9645\u7684 useState \u5b9e\u73b0\u7ecf\u8fc7\u591a\u65b9\u9762\u7684",(0,r.kt)("a",{parentName:"p",href:"https://overreacted.io/why-do-hooks-rely-on-call-order/"},"\u7efc\u5408\u8003\u8651"),"\uff0cReact \u6700\u7ec8\u9009\u62e9\u5c06 Hooks \u8bbe\u8ba1\u4e3a\u987a\u5e8f\u7ed3\u6784\uff0c\u8fd9\u4e5f\u662f Hooks \u4e0d\u80fd\u6761\u4ef6\u8c03\u7528\u7684\u539f\u56e0\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},'function mountState<S>(\n  initialState: (() => S) | S\n): [S, Dispatch<BasicStateAction<S>>] {\n  // \u521b\u5efa Hook\uff0c\u5e76\u5c06\u5f53\u524d Hook \u6dfb\u52a0\u5230 Hooks \u94fe\u8868\u4e2d\n  const hook = mountWorkInProgressHook();\n  // \u5982\u679c\u521d\u59cb\u503c\u662f\u51fd\u6570\uff0c\u5219\u8c03\u7528\u51fd\u6570\u53d6\u5f97\u521d\u59cb\u503c\n  if (typeof initialState === "function") {\n    initialState = initialState();\n  }\n  hook.memoizedState = hook.baseState = initialState;\n  // \u521b\u5efa\u4e00\u4e2a\u94fe\u8868\u6765\u5b58\u653e\u66f4\u65b0\u5bf9\u8c61\n  const queue = (hook.queue = {\n    pending: null,\n    dispatch: null,\n    lastRenderedReducer: basicStateReducer,\n    lastRenderedState: initialState,\n  });\n  // dispatch \u7528\u4e8e\u4fee\u6539\u72b6\u6001\uff0c\u5e76\u5c06\u6b64\u6b21\u66f4\u65b0\u6dfb\u52a0\u5230\u66f4\u65b0\u5bf9\u8c61\u94fe\u8868\u4e2d\n  const dispatch: Dispatch<BasicStateAction<S>> = (queue.dispatch =\n    (dispatchAction.bind(null, currentlyRenderingFiber, queue): any));\n  return [hook.memoizedState, dispatch];\n}\n')),(0,r.kt)("h4",{id:"21-\u526f\u4f5c\u7528-hook"},"2.1 \u526f\u4f5c\u7528 Hook"),(0,r.kt)("p",null,"\u6a21\u62df\u7684 useEffect \u5b9e\u73b0\uff0c\u540c\u6837\u5229\u7528\u4e86 memoizedState \u95ed\u5305\u6765\u5b58\u50a8\u4f9d\u8d56\u6570\u7ec4\u3002\u4f9d\u8d56\u6570\u7ec4\u8fdb\u884c\u6d45\u6bd4\u8f83\uff0c\u9ed8\u8ba4\u7684\u6bd4\u8f83\u7b97\u6cd5\u662f ",(0,r.kt)("inlineCode",{parentName:"p"},"Object.is"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"function useEffect(cb, depArray) {\n  const oldDeps = memoizedState[cursor];\n  let hasChange = true;\n  if (oldDeps) {\n    // \u5bf9\u6bd4\u4f20\u5165\u7684\u4f9d\u8d56\u6570\u7ec4\u4e0e\u95ed\u5305\u4e2d\u4fdd\u5b58\u7684\u65e7\u4f9d\u8d56\u6570\u7ec4\uff0c\u91c7\u7528\u6d45\u6bd4\u8f83\u7b97\u6cd5\n    hasChange = depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));\n  }\n  if (hasChange) cb();\n  memoizedState[cursor] = depArray;\n  cursor++;\n}\n")),(0,r.kt)("p",null,"\u5b9e\u9645\u7684 useEffect \u5b9e\u73b0\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"function mountEffect(\n  create: () => (() => void) | void,\n  deps: Array<mixed> | void | null\n): void {\n  return mountEffectImpl(\n    UpdateEffect | PassiveEffect, // fiberFlags\n    HookPassive, // hookFlags\n    create,\n    deps\n  );\n}\nfunction mountEffectImpl(fiberFlags, hookFlags, create, deps): void {\n  // \u521b\u5efahook\n  const hook = mountWorkInProgressHook();\n  const nextDeps = deps === undefined ? null : deps;\n  // \u8bbe\u7f6e workInProgress \u7684\u526f\u4f5c\u7528\u6807\u8bb0\n  currentlyRenderingFiber.flags |= fiberFlags; // fiberFlags \u88ab\u6807\u8bb0\u5230 workInProgress\n  // \u521b\u5efa Effect, \u6302\u8f7d\u5230 hook.memoizedState \u4e0a\n  hook.memoizedState = pushEffect(\n    HookHasEffect | hookFlags, // hookFlags \u7528\u4e8e\u521b\u5efa effect\n    create,\n    undefined,\n    nextDeps\n  );\n}\n")),(0,r.kt)("h3",{id:"3-hooks-\u5982\u4f55\u4e0e-fiber-\u5171\u540c\u5de5\u4f5c"},"3. Hooks \u5982\u4f55\u4e0e Fiber \u5171\u540c\u5de5\u4f5c"),(0,r.kt)("p",null,"\u5728\u4e86\u89e3\u5982\u4f55\u5de5\u4f5c\u4e4b\u524d\uff0c\u5148\u770b\u770b Hook \u4e0e Fiber \u7684\u90e8\u5206\u7ed3\u6784\u5b9a\u4e49\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"export type Hook = {\n  memoizedState: any, // \u6700\u65b0\u7684\u72b6\u6001\u503c\n  baseState: any, // \u521d\u59cb\u72b6\u6001\u503c\n  baseQueue: Update<any, any> | null,\n  queue: UpdateQueue<any, any> | null, // \u73af\u5f62\u94fe\u8868\uff0c\u5b58\u50a8\u7684\u662f\u8be5 hook \u591a\u6b21\u8c03\u7528\u4ea7\u751f\u7684\u66f4\u65b0\u5bf9\u8c61\n  next: Hook | null, // next \u6307\u9488\uff0c\u4e4b\u4e0b\u94fe\u8868\u4e2d\u7684\u4e0b\u4e00\u4e2a Hook\n};\n")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-js"},"export type Fiber = {\n  updateQueue: mixed, // \u5b58\u50a8 Fiber \u8282\u70b9\u76f8\u5173\u7684\u526f\u4f5c\u7528\u94fe\u8868\n  memoizedState: any, // \u5b58\u50a8 Fiber \u8282\u70b9\u76f8\u5173\u7684\u72b6\u6001\u503c\n\n  flags: Flags, // \u6807\u8bc6\u5f53\u524d Fiber \u8282\u70b9\u662f\u5426\u6709\u526f\u4f5c\u7528\n};\n")),(0,r.kt)("p",null,"\u4e0e\u4e0a\u8282\u4e2d\u7684\u6a21\u62df\u5b9e\u73b0\u4e0d\u540c\uff0c\u771f\u5b9e\u7684 Hooks \u662f\u4e00\u4e2a\u5355\u94fe\u8868\u7684\u7ed3\u6784\uff0cReact \u6309 Hooks \u7684\u6267\u884c\u987a\u5e8f\u4f9d\u6b21\u5c06 Hook \u8282\u70b9\u6dfb\u52a0\u5230\u94fe\u8868\u4e2d\u3002\u4e0b\u9762\u4ee5 useState \u548c useEffect \u4e24\u4e2a\u6700\u5e38\u7528\u7684 hook \u4e3a\u4f8b\uff0c\u6765\u5206\u6790 Hooks \u5982\u4f55\u4e0e Fiber \u5171\u540c\u5de5\u4f5c\u3002"),(0,r.kt)("p",null,"\u5728\u6bcf\u4e2a",(0,r.kt)("strong",{parentName:"p"},"\u72b6\u6001 Hook"),"\uff08\u5982 useState\uff09\u8282\u70b9\u4e2d\uff0c\u4f1a\u901a\u8fc7 queue \u5c5e\u6027\u4e0a\u7684\u5faa\u73af\u94fe\u8868\u8bb0\u4f4f\u6240\u6709\u7684\u66f4\u65b0\u64cd\u4f5c\uff0c\u5e76\u5728 updade \u9636\u6bb5\u4f9d\u6b21\u6267\u884c\u5faa\u73af\u94fe\u8868\u4e2d\u7684\u6240\u6709\u66f4\u65b0\u64cd\u4f5c\uff0c\u6700\u7ec8\u62ff\u5230\u6700\u65b0\u7684 state \u8fd4\u56de\u3002"),(0,r.kt)("p",null,"\u72b6\u6001 Hooks \u7ec4\u6210\u7684\u94fe\u8868\u7684\u5177\u4f53\u7ed3\u6784\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("p",null,(0,r.kt)("img",{parentName:"p",src:"https://user-images.githubusercontent.com/4338052/130256374-80a453a4-2084-4bb8-bfba-2344f25100c4.png",alt:"State Hook"})),(0,r.kt)("p",null,"\u5728\u6bcf\u4e2a",(0,r.kt)("strong",{parentName:"p"},"\u526f\u4f5c\u7528 Hook"),"\uff08\u5982 useEffect\uff09\u8282\u70b9\u4e2d\uff0c\u521b\u5efa effect \u6302\u8f7d\u5230 Hook \u7684 memoizedState \u4e2d\uff0c\u5e76\u6dfb\u52a0\u5230\u73af\u5f62\u94fe\u8868\u7684\u672b\u5c3e\uff0c\u8be5\u94fe\u8868\u4f1a\u4fdd\u5b58\u5230 Fiber \u8282\u70b9\u7684 updateQueue \u4e2d\uff0c\u5728 commit \u9636\u6bb5\u6267\u884c\u3002"),(0,r.kt)("p",null,"\u526f\u4f5c\u7528 Hooks \u7ec4\u6210\u7684\u94fe\u8868\u7684\u5177\u4f53\u7ed3\u6784\u5982\u4e0b\u56fe\u6240\u793a\uff1a"),(0,r.kt)("p",null,(0,r.kt)("img",{parentName:"p",src:"https://user-images.githubusercontent.com/4338052/130258719-4a2ad7d5-3a0b-4f9c-b278-1f35a0b96843.png",alt:"Effect Hook"})),(0,r.kt)("h2",{id:"\u53c2\u8003\u8d44\u6599"},"\u53c2\u8003\u8d44\u6599"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"https://overreacted.io/why-do-hooks-rely-on-call-order/"},"Why Do React Hooks Rely on Call Order?")),(0,r.kt)("li",{parentName:"ol"},(0,r.kt)("a",{parentName:"li",href:"https://medium.com/@ryardley/react-hooks-not-magic-just-arrays-cd4f1857236e"},"React hooks: not magic, just arrays"))))}k.isMDXComponent=!0}}]);