[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"categories":3,"article-15":51,"comments-15":110},[4,10,16,22,28,34,40,46],{"_id":5,"id":6,"created_at":7,"updated_at":7,"name":8,"description":8,"cover":9},"6a294c7a9fbda20eb7c62dd5",1,"2022-12-08T13:59:08.000Z","域.业务领域","\u002Fblog\u002Flighthouse.jpeg",{"_id":11,"id":12,"created_at":13,"updated_at":14,"name":15,"description":15,"cover":9},"6a294c7a9fbda20eb7c62dd6",2,"2022-12-08T13:59:56.000Z","2022-12-08T14:02:20.000Z","术.解决方案",{"_id":17,"id":18,"created_at":19,"updated_at":20,"name":21,"description":21,"cover":9},"6a294c7a9fbda20eb7c62dd7",3,"2022-12-08T14:00:22.000Z","2022-12-08T14:02:17.000Z","技.技术研究",{"_id":23,"id":24,"created_at":25,"updated_at":26,"name":27,"description":27,"cover":9},"6a294c7a9fbda20eb7c62dd8",4,"2022-12-08T14:00:33.000Z","2022-12-08T14:02:14.000Z","阵.技术应用",{"_id":29,"id":30,"created_at":31,"updated_at":32,"name":33,"description":33,"cover":9},"6a294c7a9fbda20eb7c62dd9",5,"2022-12-08T14:01:04.000Z","2022-12-08T14:02:12.000Z","法.手段方法 ",{"_id":35,"id":36,"created_at":37,"updated_at":38,"name":39,"description":39,"cover":9},"6a294c7a9fbda20eb7c62dda",6,"2022-12-08T14:01:15.000Z","2022-12-08T14:02:09.000Z","理.理论学习",{"_id":41,"id":42,"created_at":43,"updated_at":44,"name":45,"description":45,"cover":9},"6a294c7a9fbda20eb7c62ddb",7,"2022-12-08T14:01:24.000Z","2022-12-08T14:02:06.000Z","器.工具使用",{"_id":47,"id":48,"created_at":49,"updated_at":49,"name":50,"description":50,"cover":9},"6a294c7a9fbda20eb7c62ddc",8,"2022-12-08T14:01:53.000Z","杂.杂七杂八",{"_id":52,"id":53,"created_at":54,"updated_at":55,"title":56,"content":57,"description":56,"cover":58,"created_date":59,"category_id":18,"tag_ids":60,"author_ids":61,"public":6,"status":6,"star":6,"like":62,"views":63,"category":64,"tags":65,"authors":78,"related":85},"6a294c7a9fbda20eb7c62e0f",15,"2022-12-11T08:50:27.000Z","2026-06-13T10:03:54.021Z","React hooks 快速尝鲜","## React hooks 快速尝鲜\n\n### useState\n```js\nconst [num, setNum] = useState(\"0\");\n\u002F\u002F useState 函数帮我们解构了一个变量 num 和 setNum 函数，并且将变量初始值赋值为 0\n\u002F\u002F useState除了可以静态的赋值还可以useState(()=>init)\n\u002F\u002F useState返回的更新数据方法setXXX(currentState=>currentState+1)默认会传入当前的数据状态\n```\n\n### useReducer\n```jsx\n\u002F\u002F 创建一个 reducer\nfunction myReducer(state, action){\n    switch(action.type) {\n        case \"add\": return state + 1\n        case \"minus\": return state - 1\n        default: state\n    }\n}\nconst [state, dispatchNum] = useReducer(myReducer, 0)\ndispatchNum({ type: add })\n```\n\n### useEffect\n```jsx\n\u002F\u002F Effect Hook 可以让你在函数组件中执行副作用操作\n\u002F\u002F 解释这个 Hook 之前先理解下什么是副作用。网络请求、订阅某个模块或者 DOM 操作都是副作用的例子，Effect Hook是专门用来处理副作用的。正常情况下，在Function Component的函数体中，是不建议写副作用代码的，否则容易出 bug。\n\u002F\u002F useEffect 可以看做是替代了一些生命周期\nconst [num, setNum] = useState(0)\nuseEffect(() => {\n    const interval = setInterval(() => {\n        setNum(num + 1)\n    }, 1000)\n    \u002F\u002F 最后要 return 一下，记得清楚定时器\n    return () => clearInterval()\n}, [num])\n\u002F\u002F useEffect 会在组件第一次渲染时执行\n\u002F\u002F useEffect 第一个参数函数相当于生命周期中的 componentDidMount，\n\u002F\u002F useEffect 第二个参数为依赖项，当依赖项改变时才会执行 useEffect 一个参数函数，不传的话 useEffect 会在每次 DOM 渲染后执行\n\u002F\u002F useEffect 第一个参数函数返回值（return）相当于生命周期中的 componentWillUnMount\n\u002F\u002F 当useEffect 第一个参数的返回值是一个函数的时候，React 会在下一次执行这个副作用之前执行一遍清理工作，整个组件的生命周期流程可以这么理解：组件挂载 --> 执行副作用 --> 组件更新 --> 执行清理函数 --> 执行副作用 --> 组件更新 --> 执行清理函数 --> 组件卸载\n\u002F\u002F 第二个参数是一个数组，可以传多个值，一般会将 Effect 用到的所有 props 和 state 都传进去。\n\u002F\u002F 当副作用只需要在组件挂载的时候和卸载的时候执行，第二个参数可以传一个空数组[]，实现的效果有点类似componentDidMount和componentWillUnmount的组合\n```\n\n### useContext\n```jsx\n\u002F\u002F 新建一个context文件myContext.js\nimport React from 'react'\nexport default React.createContext(\"\")\n```\n\n```js\n\u002F\u002F 在另一个文件中引入\nimport MyContext from '.\u002FmyContext'\n\u002F\u002F 通过MyContext.Provider 传值\n\u003CMyContext.Provider value=\"test\">\n    \u003CComponent\u002F>\n\u003C\u002FMyContext.Provider>\n\u002F\u002F 当前的 context 值由上层组件中距离当前组件最近的 \u003CMyContext.Provider> 的 value prop 决定\n```\n\n```jsx\n\u002F\u002F 在组件中使用\nimport {useContext} from 'react'\nimport MyContext from '.\u002FmyContext'\nfunction test() {\n    const contextValue = useContext(MyContext)\n    return \u003Cdiv>{contextValue}\u003C\u002Fdiv>\n}\n```\n\n### useRef\n```jsx\nimport {useRef} from 'react'\nfunction testRef() {\n    const inputRef = useRef()\n    useEffect(() => {\n        console.log(inputRef)\n    })\n    return \u003Cinput ref={inputRef}>测试ref\u003C\u002Finput>\n}\n```\n\n### useMemo\n某些情况下组件中的值需要依赖state进行计算后得到，由于每次组件更新都会去重新计算，为了减少性能消耗，可以使用useMemo缓存值，仅仅当依赖改变时，才重新计算。\n\n* 参数：计算函数，依赖数组\n\n则函数仅会在某个依赖项改变时才重新计算memoized 值。\n```jsx\nconst [count, setCount] = useState(0);\n\u002F\u002Fexpensive 需要依赖count计算得到\n const expensive = useMemo(() => {\n let sum = 0;\n for (let i = 0; i \u003C count; i++) {\n sum += i;\n }\n return sum;\n \u002F\u002F只有count变化，这⾥才重新执⾏\n }, [count]);\n```\n\n### useCallback\n由于每次组件更新都会内部函数都会重新创建一次，为了节省性能，可以使用useCallback，使内联回调函数仅仅在传入依赖项改变时进行更新。\n\n* 参数：内联回调函数，依赖数组\n\n则函数仅会在某个依赖项改变时才进行更新。\n```jsx\n const [count, setCount] = useState(0);\n const addClick = useCallback(() => {\nsetCount（count+1）\n }, [count]);\n```\n\n### useImperativeHandle\n\n* 有些情况下我们需要父组件把ref传递给子组件，仅仅使用 forwardRef 将子组件的ref属性都暴露给父组件是危险的，也违反了封装原则，useImperativeHandle允许在子组件中把自定义实例附加到父组件传过来的ref上，减少暴露给父组件的属性\n* 参数： 3个，ref, createHandle处理函数，其返回值会替换父组件传来的ref.current, [state]依赖项\n\n```jsx\nuseImperativeHandle(ref, createHandle, [state])\n```\n\n* 例子\n\n```jsx\nlet Child =  (props, ref) =>{\n    const inputRef = useRef();\n    useImperativeHandle(ref, () => ({\n        focus: () => {\n            inputRef.current.focus()\n        }\n    }));\n    return \u003Cinput ref={inputRef} \u002F>;\n}\nChild = forwardRef(Child );\n\nconst Father=() => {\n    const ref = useRef(null);\n    return (\n        \u003C>\n            \u003CChild ref={ref}\u002F>\n             \u003Cbutton onClick={()=>{ ref.current.focus()}}>聚焦\u003C\u002Fbutton >\n        \u003C\u002F>\n    )\n}\n```\n\n### useLayoutEffect\n\n* 作用 ：与useEffect相同，都是用来执行副作用。\n* 特点 ：useEffect是在渲染之后调用effect，也就是下一桢执行，是异步的；\n而useLayoutEffect在当前帧Render tree计算布局（Layout）信息后，渲染前，同步调用effect。官方文档建议使用标准useEffec。\n\n### 自定义Hook\n\n* 定义：函数以use开头并且在函数内部调用其他hooks，并且返回一个数组，可以实现逻辑复用。\n* 例子 ：\n\n```jsx\n\u002F\u002F实现一个thunk\nconst useThunk =(reducer,initalState)=>{\nconst [state,dispatch] =useReducer(reducer,initalState)\nconst thunkDispatch = (action)=>{\nif( action instanceof Function){ \u002F\u002F如果action是函数，传入新的dispatch执行action\n   return action (thunkDispatch,()=>state)\n}else{\ndispatch(action )\n}\nreturn [state,thunkDispatch]\n}\n```\n","","2018-10-04T16:00:00.000Z",[6,12,42],[6],0,126,{"_id":17,"id":18,"created_at":19,"updated_at":20,"name":21,"description":21,"cover":9},[66,70,74],{"_id":67,"id":6,"created_at":68,"updated_at":68,"name":69},"6a294c7a9fbda20eb7c62de1","2022-12-08T14:04:04.000Z","工具方法",{"_id":71,"id":12,"created_at":72,"updated_at":72,"name":73},"6a294c7a9fbda20eb7c62de2","2022-12-08T14:04:09.000Z","工具收录",{"_id":75,"id":42,"created_at":76,"updated_at":76,"name":77},"6a294c7a9fbda20eb7c62de7","2022-12-08T14:05:07.000Z","学习记录",[79],{"name":80,"avatar":81,"email":82,"description":83,"role":84,"id":6},"Gavin","\u002Fblog\u002FWechatIMG133.jpeg","zzlwte@gmail.com","写代码的,也撸铁。白天搬 JavaScript 砖,晚上举铁,偶尔在这里写写技术沉淀和生活随想。",32,[86,90,93,97,101,105],{"id":6,"title":87,"cover":88,"created_date":89},"Docker","\u002Fblog\u002Fimg\u002F%E6%88%AA%E5%B1%8F2020-03-08%E4%B8%8B%E5%8D%889.34.21.png","2022-12-08T22:19:02.000Z",{"id":30,"title":91,"cover":58,"created_date":92},"记录 oh-my-zsh 问题","2021-06-30T16:00:00.000Z",{"id":94,"title":95,"cover":58,"created_date":96},10,"vim 窗口管理","2020-12-14T16:00:00.000Z",{"id":98,"title":99,"cover":58,"created_date":100},11,"Vim 问题集合","2020-10-20T00:00:00.000Z",{"id":102,"title":103,"cover":58,"created_date":104},9,"Vim 前端插件整理","2020-10-13T00:00:00.000Z",{"id":106,"title":107,"cover":108,"created_date":109},17,"Typescript 快速入门","\u002FFiLpf0uKN-F6iOMF7W7Ffs2mZtfk","2019-12-27T14:04:00.000Z",[]]