事情是这样的,昨天一个组件useMemo依赖太多了,被我一怒之下删掉了,而后就发现组件渲染次数直线上升,我忽然顿悟了,我对react hooks一无所知, 而后本着我本身知道的渲染逻辑,写了几个demo,打印完日志以后才发现,我何止一无所知,我写的是什么玩意??react
锁匠: 您配钥匙吗?我: 我不配
markdown
下方代码比较多, 但都是无脑的简单代码,还请按照你的理解,跟着我走一遍,看看是否是跟你理解的同样,我是被按在地上打了个细碎app
export default function Effect() {
const [name1, updateName1] = useState('name1');
const [name2, updateName2] = useState('name2');
const [name3, updateName3] = useState('name3');
useEffect(() => {
console.log('---1---');
updateName1('name1111');
console.log('---4---');
updateName2('name2222');
console.log('---3---');
updateName3('name3333');
}, []);
console.log('---render---');
return <div style={{ marginTop: '100px' }} className="doc-ui-btns">
<div>name1: {name1}</div>\
<div>name4: {name2}</div>
<div>name3: {name3}</div>
</div>;
}
复制代码
console.log('---render---');
console.log('---1---');
console.log('---4---');
console.log('---3---');
console.log('---render---');
复制代码
export default function Effect() {
const [name1, updateName1] = useState('name1');
const [name2, updateName2] = useState('name2');
const [name3, updateName3] = useState('name3');
useEffect(() => {
console.log('---1---');
updateName1('name1111');
}, []);
useEffect(() => {
console.log('---4---');
updateName2('name2222');
}, []);
useEffect(() => {
console.log('---3---');
updateName3('name3333');
}, []);
console.log('---render---');
return <div style={{ marginTop: '100px' }} className="doc-ui-btns">
<div>name1: {name1}</div>\
<div>name4: {name2}</div>
<div>name3: {name3}</div>
</div>;
}
复制代码
console.log('---render---');
console.log('---1---');
console.log('---4---');
console.log('---3---');
console.log('---render---');
跟写在一个useEffect里面同样
复制代码
export default function Effect() {
const [name1, updateName1] = useState('name1');
const [name2, updateName2] = useState('name2');
const [name3, updateName3] = useState('name3');
useEffect(() => {
setTimeout(() => {
console.log('---1---');
updateName1('name1111');
console.log('---4---');
updateName2('name2222');
console.log('---3---');
updateName3('name3333');
}, 100)
}, []);
console.log('---render---');
return <div style={{ marginTop: '100px' }} className="doc-ui-btns">
<div>name1: {name1}</div>\
<div>name4: {name2}</div>
<div>name3: {name3}</div>
</div>;
}
复制代码
console.log('---render---');
console.log('---1---');
console.log('---render---');
console.log('---4---');
console.log('---render---');
console.log('---3---');
console.log('---render---');
在异步场景中每次update都会触发render,这个和setState在异步场景的处理一致
复制代码
日后看异步
function Effect() {
const [name1, updateName1] = useState('name1');
const [name2, updateName2] = useState('name2');
const [name3, updateName3] = useState('name3');
useEffect(() => {
console.log('---1---');
updateName1('name1111');
console.log('---4---');
updateName2('name2222');
console.log('---3---');
updateName3('name3333');
}, []);
useEffect(() => {
console.log('---5---');
updateName2('name2222');
}, [name1]);
useEffect(() => {
console.log('---6---');
updateName2('name3333');
}, [name3]);
console.log('---render---');
return <div style={{ marginTop: '100px' }} className="doc-ui-btns">
<div>name1: {name1}</div>
<div>name4: {name2}</div>
<div>name3: {name3}</div>
</div>;
}
复制代码
console.log('---render---');
console.log('---1---');
console.log('---4---');
console.log('---3---');
console.log('---5---');
console.log('---6---');
console.log('---render---');
console.log('---5---');
console.log('---6---');
console.log('---render---');
你会发现5 6这两步执行了2遍,而且是合并刷新。
复制代码
function Effect() {
const [name1, updateName1] = useState('name1');
const [name2, updateName2] = useState('name2');
const [name3, updateName3] = useState('name3');
useEffect(() => {
console.log('---inner---');
setTimeout(() => {
console.log('---1---');
updateName1('name1111');
console.log('---4---');
updateName2('name2222');
console.log('---3---');
updateName3('name3333');
}, 100);
}, []);
useEffect(() => {
console.log('---5---');
updateName3('name2222');
}, [name1]);
useEffect(() => {
console.log('---6---');
updateName2('name3333');
}, [name3]);
console.log('---render---');
return <div style={{ marginTop: '100px' }} className="doc-ui-btns">
<div>name1: {name1}</div>
<div>name4: {name2}</div>
<div>name3: {name3}</div>
</div>;
}
复制代码
console.log('---render---');
console.log('---inner---');
console.log('---5---');
console.log('---6---');
console.log('---render---');
console.log('---6---');
console.log('---render---');
console.log('---1---');
console.log('---render---');
console.log('---4---');
console.log('---5---');
console.log('---render---');
console.log('---3---');
console.log('---render---');
console.log('---6---');
console.log('---render---');
复制代码
这里问题出来了,4和5怎么被合并了????这是2个Effect里面的东西啊, 4是在异步状态里面,按照异步场景1: 多个update在异步函数中
这个检测结果,在异步中的事件应该是每update一次,页面就render一次,如今倒是4/5合并了!!函数
这里--5--
这个effect里面正好依赖了异步中第一次修改的name1
, 因此在update name1以后,跟随下一次update,而且在下一次update以后处理了反作用因此就有了先打印4再打印5, 若是吧--6--
里面的依赖改为name2
那么在updateName2以后3和6也会被合并ui
总结: 在异步操做中,每次update以后的反作用会跟着下一次update执行,而且在下一次update以后执行url
export default function ToastPage() {
const [name1, updateName1] = useState('name1');
const [name2, updateName2] = useState('name2');
const [name3, updateName3] = useState('name3');
const [name4, updateName4] = useState('name4');
useEffect(() => {
console.log('----第一次变动---');
setTimeout(() => {
console.log('---1---');
updateName1('name1111');
console.log('---2---');
updateName4('name1444444');
console.log('---3---');
updateName3('name133333');
}, 100);
}, []);
useEffect(() => {
console.log('---4---');
updateName3('name333333');
console.log('---5---');
updateName4('name544444');
}, [name1]);
useEffect(() => {
console.log('---6---');
updateName2('name344444');
}, [name4]);
console.log('---render---');
return <div style={{ marginTop: '100px' }} className="doc-ui-btns">
<div>name1: {name1}</div>
<div>name3: {name3}</div>
<div>name4: {name4}</div>
</div>;
}
复制代码
console.log('---render---');
console.log('----第一次变动---');
console.log('---4---');
console.log('---5---');
console.log('---6---');
console.log('---render---');
console.log('---6---');
console.log('---render---');
console.log('---1---');
console.log('---render---');
console.log('---2---');
console.log('---4---');
console.log('---5---');
// 问题出在这里,执行5以后实际上是update了name4 除此以外执行2的时候也更新了name4,可是下方依赖name4变动的6却没有被执行, 而是直接下一步执行了3 而后render就结束了??
console.log('---render---');
console.log('---3---');
console.log('---render---');
上面这个流程,若是把 console.log('---5---'); updateName4('name544444');这两行删掉, --6--这个依赖就会正常执行。
我也不知道为何...
复制代码
function ToastPage() {
const [name1, updateName1] = useState('name1');
const [name2, updateName2] = useState('name2');
const [name3, updateName3] = useState('name3');
const [name4, updateName4] = useState('name4');
useEffect(() => {
console.log('----第一次变动---');
setTimeout(() => {
console.log('---1---');
updateName1('name1111');
console.log('---2---');
updateName4('name1444444');
console.log('---3---');
updateName3('name133333');
}, 100);
}, []);
useEffect(() => {
console.log('----变动了name1---');
setTimeout(() => {
console.log('---4---');
updateName3('name333333');
console.log('---5---');
updateName4('name544444');
}, 100);
}, [name1]);
useEffect(() => {
console.log('---6---');
updateName2('name344444');
}, [name4]);
console.log('---render---');
return <div style={{ marginTop: '100px' }} className="doc-ui-btns">
<div>name1: {name1}</div>
<div>name1: {name2}</div>
<div>name3: {name3}</div>
<div>name4: {name4}</div>
</div>;
}
复制代码
console.log('---render---');
console.log('----第一次变动---');
console.log('----变动了name1---');
console.log('---6---');
console.log('---render---');
//上面是第一阶段,执行完了同步的effect,下面开始执行异步
console.log('---1---');
console.log('---render---');
console.log('---2---');// 这2个合并,
console.log('----变动了name1---'); // 可是合并以后的effect是异步,因此只打印了入口
console.log('---render---'); // 合并以后render
console.log('---3---'); 3 6合并,这时候依然在处理第一个异步
console.log('---6---');
console.log('---render---'); // 合并以后处理异步
console.log('---4---'); // 开始处理第二个异步,这个实际上是第一轮执行useEffect的时候产生的
console.log('---render---'); // 遵循了 update一次render一次
console.log('---5---');
console.log('---render---');
console.log('---6---');
console.log('---render---');
console.log('---4---'); // 这是name1变动后又进来了反作用产生的异步操做,可是一次都没有render
console.log('---5---');
没有render
复制代码
上面的执行逻辑中仍是有规律可寻的spa
异步+依赖场景2
中,有一次effect为何会被忽略掉异步套异步会怎么样?
中,为何产生的异步反作用会只update不刷新。