第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

React 組件有時(shí)會(huì)在狀態(tài)不變的情況下渲染兩次

React 組件有時(shí)會(huì)在狀態(tài)不變的情況下渲染兩次

撒科打諢 2022-06-05 11:13:17
我正在使用 Redux 訂閱商店并更新組件。這是一個(gè)沒有 Redux 的簡(jiǎn)化示例。它使用模型商店進(jìn)行訂閱和分發(fā)。請(qǐng)按照片段下方的步驟重現(xiàn)問題。編輯:請(qǐng)?zhí)礁孪碌牡诙€(gè)演示片段,以獲得更簡(jiǎn)潔和更接近現(xiàn)實(shí)生活的場(chǎng)景。問題不在于 Redux。這是關(guān)于 React 的 setState 函數(shù)標(biāo)識(shí)在某些情況下導(dǎo)致重新渲染,即使?fàn)顟B(tài)沒有改變。編輯 2 :在“更新 2 ”下添加了更簡(jiǎn)潔的演示。const {useState, useEffect} = React;let counter = 0;const createStore = () => {    const listeners = [];        const subscribe = (fn) => {        listeners.push(fn);        return () => {            listeners.splice(listeners.indexOf(fn), 1);        };    }        const dispatch = () => {        listeners.forEach(fn => fn());    };        return {dispatch, subscribe};};const store = createStore();function Test() {    const [yes, setYes] = useState('yes');        useEffect(() => {        return store.subscribe(() => {            setYes('yes');        });    }, []);        console.log(`Rendered ${++counter}`);        return (        <div>            <h1>{yes}</h1>            <button onClick={() => {                setYes(yes === 'yes' ? 'no' : 'yes');            }}>Toggle</button>            <button onClick={() => {                store.dispatch();            }}>Set to Yes</button>        </div>    );}ReactDOM.render(<Test />, document.getElementById('root'));<div id="root"></div><script src="https://unpkg.com/react/umd/react.development.js"></script><script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>怎么了? 單擊“設(shè)置為是”。由于 的值yes已經(jīng)是“yes”,狀態(tài)沒有改變,因此組件不會(huì)重新渲染。? 點(diǎn)擊“切換”。yes設(shè)置為“否”。狀態(tài)已經(jīng)改變,所以組件被重新渲染。? 單擊“設(shè)置為是”。yes設(shè)置為“是”。狀態(tài)再次改變,所以組件被重新渲染。? 再次單擊“設(shè)置為是”。狀態(tài)沒有改變,但組件仍然重新渲染。? 后續(xù)點(diǎn)擊“設(shè)置為是”不會(huì)按預(yù)期導(dǎo)致重新渲染。預(yù)計(jì)會(huì)發(fā)生什么在第 4 步,不應(yīng)重新渲染組件,因?yàn)闋顟B(tài)未更改。
查看完整描述

2 回答

?
白衣非少年

TA貢獻(xiàn)1155條經(jīng)驗(yàn) 獲得超0個(gè)贊

答案是 React 使用一組啟發(fā)式方法來確定它是否可以避免再次調(diào)用渲染函數(shù)。這些啟發(fā)式方法可能會(huì)在版本之間發(fā)生變化,并且不能保證在狀態(tài)相同時(shí)總是退出。React 提供的唯一保證是,如果狀態(tài)相同,它不會(huì)重新渲染子組件。

你的渲染函數(shù)應(yīng)該是純的。因此,它們運(yùn)行多少次并不重要。如果您在渲染函數(shù)中計(jì)算一些昂貴的東西并且擔(dān)心調(diào)用它而不是必要的,您可以將該計(jì)算包裝在useMemo.

一般來說,React 中的“計(jì)數(shù)渲染”是沒有用的。React 何時(shí)調(diào)用您的函數(shù)取決于 React 本身,并且確切的時(shí)間將在版本之間不斷變化。這不是合同的一部分。


查看完整回答
反對(duì) 回復(fù) 2022-06-05
?
斯蒂芬大帝

TA貢獻(xiàn)1827條經(jīng)驗(yàn) 獲得超8個(gè)贊

這似乎是一種預(yù)期的行為。

來自React 文檔

擺脫狀態(tài)更新

如果您將 State Hook 更新為與當(dāng)前狀態(tài)相同的值,React 將退出而不渲染子級(jí)或觸發(fā)效果。(React 使用Object.is比較算法。)

請(qǐng)注意,React 可能仍需要在退出之前再次渲染該特定組件。這不應(yīng)該是一個(gè)問題,因?yàn)?React 不會(huì)不必要地“深入”到樹中。如果您在渲染時(shí)進(jìn)行昂貴的計(jì)算,您可以使用useMemo.

因此,React確實(shí)在第一個(gè)演示的第 4 步和第二個(gè)演示的第 3 步重新渲染了組件。因此,它執(zhí)行函數(shù)內(nèi)的所有代碼,并調(diào)用React.createElement()組件的每個(gè)子組件。

但是,它不會(huì)渲染組件的任何后代,也不會(huì)觸發(fā)效果。

這僅適用于功能組件。對(duì)于純類組件,render如果狀態(tài)未更改,則永遠(yuǎn)不會(huì)調(diào)用該方法。

我們無法避免重新運(yùn)行。記住這個(gè)函數(shù)memo()也無濟(jì)于事,因?yàn)?a >它只檢查 props的變化,而不是狀態(tài)。所以我們只需要考慮這種情況。

這并不能回答 React 為什么以及何時(shí)運(yùn)行該函數(shù)但退出,以及何時(shí)它根本不運(yùn)行該函數(shù)的問題。如果您知道原因,請(qǐng)?zhí)砑幽拇鸢浮?/p>


查看完整回答
反對(duì) 回復(fù) 2022-06-05
  • 2 回答
  • 0 關(guān)注
  • 748 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)