额外的 Hook 大部分为性能优化所提供
- 优化需要成本
- 过度的优化只会让性能变得更差
- 避免为了测试学习而使用额外的 hook
useEffect
1 | useEffect(didUpdate: function, conditions: Array); |
useEffect 内部调用的函数,应该在 useEffect 函数内部声明,以避免BUG 发生
useState
当创建的 state 并不发生昂贵的计算时
1 | const [count, setCount] = useState(0); |
当发生昂贵的计算时,因使用函数来返回需要的值,这样一来 react 仅会在首次渲染时调用这个函数
1 | const [rows, setRows] = useState(() => createRows(props.count)); |
详情请参考如何惰性创建昂贵的对象?
useMemo
你可以把 useMemo 作为一种性能优化的手段,但不要把它当做一种语义上的保证。
useMemo 也允许你跳过一次子节点的昂贵的重新渲染:
1 | function Parent({ a, b }) { |
详细请参考: 如何记忆计算结果?
hooks 如何避免向下传递回调?
详细请参考: 如何避免向下传递回调?
useRef 的应用
避免使用 refs 来做任何可以通过声明式实现来完成的事情。
举个例子,避免在
Dialog
组件里暴露open()
和close()
方法,最好传递isOpen
属性。
- 管理焦点,文本选择或媒体播放。
- 触发强制动画。
- 集成第三方 DOM 库。
hook 的方式和 class 的方式区别:
class:
hooks:
1 | function TextInputWithFocusButton() { |
使用 ref
时自定义暴露给父组件的实例值
1 | function FancyInput(props, ref) { |
在本例中,渲染 <FancyInput ref={inputRef} />
的父组件可以调用 inputRef.current.focus()
。
useLayoutEffect 的使用场景
- 非服务端渲染
- useEffect 出问题的时候再尝试使用
useCallback 使用场景
useCallback
并非避免重新创建内部函数的工具
有一篇不错的经验者的文章,如果想了解详细可以参考
因为函数式组件每次重新渲染也会重新创建内部创建的方法,所以向下传递给的子组件因为props
的变化而发生重新渲染(期待的情况是,仅函数内部依赖值发生变化时重新创建并向下传递)
useCallback
和React.memo
一般同时使用,来避免组件内部渲染时,非必要的子组件重新渲染