事情是這樣的,昨天一個組件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不刷新。