后端的React之路(十二)

65 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

前言

这两天学习了React新版本所带来的Hook特性,也是感觉到它所带来的便利,但在学习过程中还是踩了一些坑,下面就来记录一下。

React中Hook可能踩的坑

hook定义规则

官方有两条Hook定义规则:

  1. 只在最顶层使用 Hook
  2. 只在 React 函数中调用 Hook

第一条规则即不要在if-else等条件控制语句中调用Hook,这会导致Hook的执行顺序出现问题,从而导致BUG。如果我们想要根据条件执行Hook,就将条件控制语句放置Hook中。

 // 🔴 在条件语句中使用 Hook 违反第一条规则
  if (name !== '') {
    useEffect(function persistForm() {
      localStorage.setItem('formData', name);
    });
  }
 
 useEffect(function persistForm() {
    // 👍 将条件判断放置在 effect 中
    if (name !== '') {
      localStorage.setItem('formData', name);
    }
  });

第二条规则则是因为普通函数本身并不能保存状态本身,例如下面的例子代码:如果有开启eslint编译的话,就会抛出一个错误。

import React, {useEffect} from 'react';
import ReactDOM from 'react-dom/client';
​
​
function normalFunction() {
    useEffect( () => {
        console.log( "Hello" );
    } )
​
    return (<div>subDom</div>)
}
​
function Demo() {
​
    useEffect( () => {
        console.log( "只执行一次" );
    }, [] )
    return (
            <>
                <div>
                    DEMO
                </div>
                {normalFunction()}
            </>
    );
}
​
let root = ReactDOM.createRoot(
        document.getElementById( "root" )
);
root.render( <Demo/> )
​
// React Hook "useEffect" is called in function "normalFunction" that is neither a React function component nor a custom React Hook function.

如果我们强制执行,这个普通函数所定义的Hook都会挂载到其调用的父组件去,在如上的例子就是会由Demo组件来挂载。

useEffect重复调用

有时会发现useEffect一直在执行,这可能是因为在函数中更改了state从而导致dom刷新,一直触发useEffect(),这时我们就需要定义对应的deps参数了。

import React, {useEffect, useState} from 'react';
import ReactDOM from 'react-dom/client';
​
​
function Demo() {
​
    const [str, setStr] = useState( "default" )
​
    useEffect( () => {
        console.log( "useEffect被执行" ); // 不断被执行
        setStr( Math.random().toString() )
    } )
​
    return (
            <div>
                {str}
            </div>
​
​
    );
}
​
let root = ReactDOM.createRoot(
        document.getElementById( "root" )
);
root.render( <Demo/> )

useEffect未调用

有时我们定义了useEffect对应的依赖项deps,却发现更改state后,useEffect却没有被调用。可能是因为React是通过浅比较来判断值是否发生了变化,才决定是否调用useEffect。例如我们定义一个对象数组,只修改其中一个对象的属性,这时React是无法感知的。

学习资料