React Hooks在平时开发中需要注意的事项?


一、注意的问题?

(1)不要在循环,条件或嵌套函数中调用Hook,必须始终在 React函数的顶层使用Hook

这是因为React需要利用调用顺序来正确更新相应的状态,以及调用相应的钩子函数。一旦在循环或条件分支语句中调用Hook,就容易导致调用顺序的不一致性,从而产生难以预料到的后果。

(2)使用useState时候,使用push,pop,splice等直接更改数组对象的坑

使用push直接更改数组无法获取到新值,应该采用析构方式,但是在class里面不会有这个问题。

(3)useState设置状态的时候,只有第一次生效,后期需要更新状态,必须通过useEffect

TableDeail是一个公共组件,在调用它的父组件里面,我们通过set改变columns的值,以为传递给TableDeail 的 columns是最新的值,所以tabColumn每次也是最新的值,但是实际tabColumn是最开始的值,不会随着columns的更新而更新:

(4)善用useCallback

父组件传递给子组件事件句柄时,如果我们没有任何参数变动可能会选用useMemo。但是每一次父组件渲染子组件即使没变化也会跟着渲染一次。

(5)不要滥用useContext

可以使用基于 useContext 封装的状态管理工具。

二、hook和生命周期的关系?

函数组件 的本质是函数,没有 state 的概念的,因此不存在生命周期一说,仅仅是一个 render 函数而已。
但是引入 Hooks 之后就变得不同了,它能让组件在不使用 class 的情况下拥有 state,所以就有了生命周期的概念,所谓的生命周期其实就是 useState、 useEffect() 和 useLayoutEffect() 。

即:Hooks 组件(使用了Hooks的函数组件)有生命周期,而函数组件(未使用Hooks的函数组件)是没有生命周期的。

下面是具体的 class 与 Hooks 的生命周期对应关系:

constructor:函数组件不需要构造函数,可以通过调用 useState 来初始化 state。如果

计算的代价比较昂贵,也可以传一个函数给 useState。
const [num, UpdateNum] = useState(0)

getDerivedStateFromProps:一般情况下,我们不需要使用它,可以在渲染过程中更新 state,以达到实现 getDerivedStateFromProps 的目的。

function ScrollView({
     
     row}) {
    
    
  let [isScrollingDown, setIsScrollingDown] = useState(false);
  let [prevRow, setPrevRow] = useState(null);
  if (row !== prevRow) {
    
    
    // Row 自上次渲染以来发生过改变。更新 isScrollingDown。
    setIsScrollingDown(prevRow !== null && row > prevRow);
    setPrevRow(row);
  }
  return `Scrolling down: ${
      
      isScrollingDown}`;
}

React 会立即退出第一次渲染并用更新后的 state 重新运行组件以避免耗费太多性能。

shouldComponentUpdate:可以用 React.memo 包裹一个组件来对它的 props 进行浅

比较
const Button = React.memo((props) => {
    
      // 具体的组件});

注意:**React.memo 等效于 **``PureComponent,它只浅比较 props。这里也可以使用 useMemo 优化每一个节点。

render:这是函数组件体本身。
componentDidMount, componentDidUpdate: useLayoutEffect 与它们两的调用阶段是一样的。但是,我们推荐你一开始先用 useEffect,只有当它出问题的时候再尝试使用 useLayoutEffect。useEffect 可以表达所有这些的组合。

// componentDidMount
useEffect(()=>{
    
    
  // 需要在 componentDidMount 执行的内容
}, [])
useEffect(() => {
    
     
  // 在 componentDidMount,以及 count 更改时 componentDidUpdate 执行的内容
  document.title = `You clicked ${
      
      count} times`; 
  return () => {
    
    
    // 需要在 count 更改时 componentDidUpdate(先于 document.title = ... 执行,遵守先清理后更新)
    // 以及 componentWillUnmount 执行的内容       
  } // 当函数中 Cleanup 函数会按照在代码中定义的顺序先后执行,与函数本身的特性无关
}, [count]); // 仅在 count 更改时更新

请记得 React 会等待浏览器完成画面渲染之后才会延迟调用 ,因此会使得额外操作很方便

componentWillUnmount:相当于 useEffect 里面返回的 cleanup 函数
// componentDidMount/componentWillUnmount
useEffect(()=>{
    
    
  // 需要在 componentDidMount 执行的内容
  return function cleanup() {
    
    
    // 需要在 componentWillUnmount 执行的内容      
  }
}, [])

componentDidCatch and getDerivedStateFromError:目前还没有这些方法的 Hook 等价写法,但很快会加上。

class 组件 Hooks 组件
constructor useState
getDerivedStateFromProps useState 里面 update 函数
shouldComponentUpdate useMemo
render 函数本身
componentDidMount useEffect
componentDidUpdate useEffect
componentWillUnmount useEffect 里面返回的函数
componentDidCatch
getDerivedStateFromError

猜你喜欢

转载自blog.csdn.net/weixin_61102579/article/details/129154723