react中使用useEffect模拟componentDidUpdata(使 useEffect 在渲染时不执行,只在数据变更时执行)
·
背景介绍
在列表搜索条件变化时,需要保存搜索条件,但是保存搜索条件这个方法不需要在组件挂载时执行,即如何使 useEffect 在渲染时不执行,只在数据变更时执行(即模拟类组件的componentDidUpdata)
问题描述
如果是使用监听搜索条件的话,在组件加载时也会执行
/**
* title: useEffect
* desc: 打开控制台查看打印结果
*/
import React, { useState, useEffect } from 'react';
export default () => {
const [pageNum, setPageNum] = useState(1);
const saveData = () => {
console.log('useEffect----', `保存数据${pageNum}`);
};
useEffect(() => {
saveData();
}, [pageNum]);
return (
<div>
<button onClick={() => setPageNum(pageNum + 1)}>翻页{pageNum}</button>
</div>
);
};
解决方案
使用 useState
/**
* title: useState
* desc: 打开控制台查看打印结果
*/
import React, { useState, useEffect } from 'react';
export default () => {
const [pageNum, setPageNum] = useState(1);
const [isInit, setInit] = useState(true);
const saveData = () => {
console.log('useState----', `保存数据${pageNum}`);
};
useEffect(() => {
if (isInit) {
console.log('初次渲染');
setInit(false);
} else {
saveData();
}
}, [setPageNum]);
return (
<div>
<button onClick={() => setPageNum(pageNum + 1)}>翻页{pageNum}</button>
</div>
);
};
使用 useRef
/**
* title: 使用useRef
* desc: 打开控制台查看打印结果
*/
import React, { useState, useEffect, useRef } from 'react';
export default () => {
const [pageNum, setPageNum] = useState(1);
const mounting = useRef(true);
const saveData = () => {
console.log('useRef----', `保存数据${pageNum}`);
};
useEffect(() => {
if (mounting.current) {
console.log('初次渲染');
mounting.current = false;
} else {
saveData();
}
}, [pageNum]);
return (
<div>
<button onClick={() => setPageNum(pageNum + 1)}>翻页{pageNum}</button>
</div>
);
};
深度思考
使用普通变量,变量在组件内部
/**
* title: insideVar
* desc: 打开控制台查看打印结果
*/
import React, { useState, useEffect } from 'react';
export default () => {
const [pageNum, setPageNum] = useState(1);
let isInit = true;
const saveData = () => {
console.log('inside----', `保存数据${pageNum}`);
};
useEffect(() => {
if (isInit) {
console.log('inside----', '初次渲染');
isInit = false;
} else {
saveData();
}
}, [pageNum]);
return (
<div>
<button onClick={() => setPageNum(pageNum + 1)}>Demo3-翻页{pageNum}</button>
</div>
);
};
使用普通变量,变量在组件外部
/**
* title: outsideVar
* desc: 打开控制台查看打印结果
*/
import React, { useState, useEffect } from 'react';
let isInit = true;
export default () => {
const [pageNum, setPageNum] = useState(1);
const saveData = () => {
console.log('outsideVar----', `保存数据${pageNum}`);
};
useEffect(() => {
if (isInit) {
console.log('outsideVar----', '初次渲染');
isInit = false;
} else {
saveData();
}
}, [pageNum]);
return (
<div>
<button onClick={() => setPageNum(pageNum + 1)}>翻页{pageNum}</button>
</div>
);
};
Q:这两种写法有什么区别呢,为什么第一种写法(使用普通变量,变量在组件内部)一直是初次渲染呢
A: 每次重新渲染,函数组件都会被执行,内部的变量都会被重新声明
Q: 解决方案中 useState 和 useRef 的优劣
A: todo( 需要在研究 hooks 源码之后确认 2022.1201)
参考资料
React hook —如何使 useEffect 在渲染时不执行,只在数据变更时执行
更多推荐
所有评论(0)