前言
此篇为我从 Vue 转 React,初学 React Hook 的一些记录,记录一些写法和注意项。
useState
此 hook 相当于 Vue 中 Date 函数返回的对象的值,返回一个数组:
1 | // state: 对应的值 |
useState
的两种写法:
1 | // 对于简单值可直接设置 |
setState
有两种使用方式:
1 | // 直接设置新值 |
useEffect
此 hook 相当于 Vue 的 updated 钩子,其会在组件渲染到屏幕之后延迟执行(会保证在任何新的渲染前执行),也可以配置让其仅在某些值改变的时候执行:
1 | // return 方法用于清楚一些副作用函数(如:removeEventListener) |
如果需要在所有 DOM 变动之后同步调用 effect,则需要使用到
useLayoutEffect
,但推荐一开始时优先使用useEffect
方法。
若要从服务端渲染的 HTML 中排除依赖布局 effect 的组件,可以通过使用
showChild && <Child />
进行条件渲染,并使用useEffect(() => { setShowChild(true); }, [])
延迟展示组件。这样,在客户端渲染完成之前,UI 就不会像之前那样显示错乱了。(如弹框组件初始化问题)
useContext
可以理解为 Vue 的 Provide/Inject 钩子(不是 ProvideReactive/InjectReactive):
1 | const MyContext = React.createContext(/* default value */); |
Provider 内如果绑定了 value(即使是 undefined),
default value
也不会生效
useReducer
简化版的 Redux
,与 useState
的区别是需要配置 reducer 函数,处理不同 type 的操作。
项目开发可能使用的不是很多,不做过多记录
useCallback
可以理解成 Vue 的 computed
钩子,不过其记录的是函数,使其仅在依赖项变更时才更新函数。当依赖参数不经常变时,可以优化子组件的渲染(返回的是子组件)。
1 | // 依赖项数组不会作为参数传给回调函数 |
此 hook
useCallback(fn, deps)
相当于useMemo(() => fn, deps)
。
注:滥用的话不仅不会提升性能,反而会降低性能。
useMemo
相当于 Vue 的 computed
钩子了,有助于避免在每次渲染时都进行高开销的计算。
1 | const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); |
传入
useMemo
的函数会在渲染期间执行。请不要在这个函数内部执行与渲染无关的操作,诸如副作用这类的操作属于useEffect
的适用范畴,而不是useMemo
。
大致流程:Dom 变更 -> useMemo -> 所有 Dom 渲染完成 -> useEffect
useRef
可以理解成 Vue 的 Ref
钩子,但是其不仅仅局限于保存 DOM 节点,其 .current
属性中可以保存一个可变值。
1 | const refContainer = useRef(initialValue); |
useRef()
和自建一个{current: ...}
对象的唯一区别是,useRef
会在每次渲染时返回同一个 ref 对象。
注: 当 ref 对象内容发生变化时,useRef
并不会通知你。变更.current
属性不会引发组件重新渲染。
useImperativeHandle
增强版 useRef
,可以自定义设置在使用 ref
时需要暴露给父组件的实例值,且useImperativeHandle
应当与 forwardRef
一起使用:
1 | // 基本方法 |
在大多数情况下,应当避免使用 ref 这样的命令式代码,可考虑使用
useImperativeHandle
做一层属性上的封装。
useLayoutEffect
它会在所有的 DOM 变更之后同步调用 effect,在浏览器执行绘制之前,useLayoutEffect
内部的更新计划将被同步刷新。
尽可能使用标准的
useEffect
以避免阻塞视觉更新。useLayoutEffect
与componentDidMount
、componentDidUpdate
的调用阶段是一样的。
useDebugValue
useDebugValue
可用于在 React 开发者工具中显示自定义 hook 的标签。
1 | function useFriendStatus(friendID) { |
不推荐你向每个自定义 Hook 添加 debug 值。当它作为共享库的一部分时才最有价值。