useEffect使用注意事项

前言

只有当依赖关系被改变时,useEffect hook 才会触发回调函数。而且它使用浅比较法来比较 hooks 的值。

1、依赖项是函数

import './App.css';
import { useEffect, useState } from 'react';

function App() {
 const [num,setNum] = useState(0);
 var mark1 = function () {
   return "100";
 }; // 唯一的对象引用

 useEffect(()=>{
   console.log("useEffect");
 },[mark1]) // render每次更新都会执行,这个依赖无意义

 return (
   <div>
     <header>
       <button onClick={()=>setNum(num+1)}>点击我改变</button>
     </header>
   </div>
 );
}
export default App;

报错警告: The ‘mark1’ function makes the dependencies of useEffect Hook (at line 14) change on every render. Move it inside the useEffect callback. Alternatively, wrap the definition of ‘mark1’ in its own useCallback() Hook react-hooks/exhaustive-deps

  • 由于 useEffect 使用浅层比较法来比较数值。该函数的浅层比较将总是给出 false

如何改进?用useCallback

  • useCallback 返回一个memoized 版本的回调,只在依赖关系改变时才会改变。
import { useCallback, useEffect, useState } from 'react';

function App() {
  const [num,setNum] = useState(0);
  
  var mark1 = useCallback(()=> {
    return "100";
  },[]);
  
  useEffect(()=>{
    console.log("useEffect");
  },[mark1])

  return (
    <div>
      <header>
        <button onClick={()=>setNum(num+1)}>点击我改变</button>
      </header>
    </div>
  );
}

export default App;

2、依赖项是数组

import { useEffect, useState } from 'react';

function App() {

  const [num,setNum] = useState(0);

  var dep = ['a']

  useEffect(()=>{
    console.log("useEffect");
  },[dep]) // 依赖项在每次渲染时都发生变化

  return (
    <div>
      <header>
        <button onClick={()=>setNum(num+1)}>点击我改变</button>
      </header>
    </div>
  );
}

export default App;

警告: The ‘dep’ array makes the dependencies of useEffect Hook (at line 11) change on every render. Move it inside the useEffect callback. Alternatively, wrap the initialization of ‘dep’ in its own useMemo() Hook react-hooks/exhaustive-dep

  • 两个数组的浅层比较总是假的,所以 useEffect 总是会触发回调[]===[] 的结果为false

如何解决?useRef

useRef 返回一个可变的对象,.current 具有初始值

import { useEffect, useRef, useState } from 'react';

function App() {

  const [num,setNum] = useState(0);
  // var dep = ['a'];
  const dep2 = useRef(['a']);

  useEffect(()=>{
    console.log("useEffect");
  },[dep2.current]) //

  return (
    <div>
      <header>
        <button onClick={()=>setNum(num+1)}>点击我改变</button>
      </header>
    </div>
  );
}
export default App;

3、将对象作为依赖

{}==={}为false对象的浅层比较将永远是假的,所以它将触发 useEffect 的回调。

如果修复这个问题?用useMemo 的 hook

如果我们将依赖关系备忘化,我们就能打破无限循环。

  • useMemo 只有在依赖关系发生变化时才会重新计算记忆化的值。
import { useEffect, useMemo, useRef, useState } from 'react';

export default function App() {
  const [count, setCount] = useState(0);
  const data = useMemo(
    () => ({
      is_fetched: false,
    }),
    []
  ); // <- dependencies
  useEffect(() => {
    setCount(count + 1);
  }, [data]);

  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <button onClick={() => setCount(count + 1)}>{count}</button>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

参考来自:https://zhuanlan.zhihu.com/p/412283445

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值