Skip to main content

如果 useEffect 依赖项为对象,是否进行更新渲染?

react hooks 的依赖项目可以按照数据类型分为基本数据类型引用数据类型

基本数据类型

useEffect 可以根据依赖项的变化而去发生改变

const [count, setCount] = useState[0];

useEffect(() => {
console.log(count);
}, [count]);

引用数据类型

useeffect总是会被触发,因为 useEffect 这里进行的是浅比较,对象与对象互不相等(即使数据一致地址也不相同),即

{a: 1} === {a: 1}的结果总为false

const [obj, setObj] = useState({});

useEffect(() => {
console.log(obj);
}, [obj]);

注意:只要我们组件中有 obj 更新,即使 obj 完全没有变化,也会打印出 obj,因为 useEffect 作的是浅比较,始终会返回 false

解决方法

使用useDeepCompareEffect深比较

将 useEffect 方法替换成 useDeepCompareEffect 即可

import useDeepCompareEffect from "use-deep-compare-effect";

useDeepCompareEffect(() => {
console.log("deep-keys", defaultKeys);
}, [defaultKeys]);

第二种:使用useRef

只需要写个 usePrevious 的钩子方法即可

import React, { useEffect, useRef, useState } from "react";

// 把对象缓存起来
function usePrevious(value) {
const ref = useRef();

useEffect(() => {
ref.current = value;
}, [value]);

return ref.current;
}

const ClickCount = () => {
const [obj, setObj] = useState({ a: 1 });
const prevObj = usePrevious(obj);

useEffect(() => {
prevObj && prevObj.a < obj.a && console.log("do something");
}, [obj]);

return (
<div>
<button
onClick={() => {
setObj({ a: obj.a + 1 });
}}
>
click
</button>
</div>
);
};

export default ClickCount;

这里用 useRef 保存了之前的数据, useEffect 中的依赖以然为引用类型, 每次 obj 发生改变都会调用执行函数,但是执行函数中多了一个判断, prevObj 是上一次渲染时 obj 的值, 用 prevObj 中的某个 key 与此次 obj 中的某个 key 做对比,满足条件后做其他操作,这也是解决方法之一。

参考文章

https://blog.csdn.net/alison_z/article/details/108752306 > https://blog.csdn.net/qq_39776508/article/details/118485896 > https://www.jianshu.com/p/fd17ce2d7e46 > https://segmentfault.com/q/1010000020429184 > https://jishuin.proginn.com/p/763bfbd607d7 > https://www.readfog.com/a/1642414651295764480