我們有一個大網格,渲染了許多昂貴的組件。為了減少頁面上的負載,我們使用虛擬化串列,并且只在任何給定時刻渲染可見部分。這意味著每當有人滾動時,由于先前在可見區域之外的組件第一次渲染時會出現白色閃光。
為了解決這個問題,我們可以定義一個“過掃描”區域 - 在滾動時立即可見的可見區域周圍渲染的專案數量。不幸的是,這意味著這些組件現在隨頁面狀態一起更新,在我們的情況下,對于任何合理的過掃描量來說,這都是一項昂貴的操作。
我想解決這個會推遲更新/渲染組件的可見區域之外的生命周期時呼叫堆疊清零,利用一個方式setTimeout,或者使用requestIdleCallback。我在 React 16/17 中找不到這樣做的方法 - 有什么想法嗎?
uj5u.com熱心網友回復:
您可以為組件提供一個屬性,告訴它們它們是否處于過掃描狀態,并為前一個和當前的 props設定shouldComponentUpdatereturn falseif inOverscanis true(或者如果使用函陣列件,則React.memo比較函式將回傳trueif inOverscanis truefor the previous and current props)當前道具)。
下面是一個例子:
顯示代碼片段
const { useState, Component } = React;
class Example1 extends Component {
shouldComponentUpdate(nextProps) {
return !nextProps.inOverscan || !this.props.inOverscan
}
render() {
const {inOverscan, value} = this.props;
return <div>
Example1 - inOverscan = {String(inOverscan)} - value = {String(value)}
</div>;
}
}
const Example2 = React.memo(
({inOverscan, value}) => {
return <div>
Example2 - inOverscan = {String(inOverscan)} - value = {String(value)}
</div>;
},
// Beware that the return value for `memo`'s comparison
// function is the opposite of the one for
// `shouldComponentUpdate`
(prevProps, nextProps) => nextProps.inOverscan && prevProps.inOverscan
);
const App = () => {
const [value, setValue] = useState(0);
const [inOverscan1, setInOverscan1] = useState(true);
const [inOverscan2, setInOverscan2] = useState(true);
const incrementValue = () => setValue(value => value 1);
return <div>
<div>
App - value = {String(value)}
</div>
<div>
<input type="button" value="Increment value" onClick={() => setValue(value => value 1)} />
</div>
<div>
<label>
<input type="checkbox" checked={inOverscan1} onChange={(e) => setInOverscan1(e.target.checked)} />
Example1 in overscan
</label>
</div>
<div>
<label>
<input type="checkbox" checked={inOverscan2} onChange={(e) => setInOverscan2(e.target.checked)} />
Example2 in overscan
</label>
</div>
<hr/>
<Example1 inOverscan={inOverscan1} value={value} />
<Example2 inOverscan={inOverscan2} value={value} />
</div>;
};
ReactDOM.render(<App />, document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.development.js"></script>
如果你運行它,你會看到最初,遞增value不會重新渲染Example1或Example2. 但是,如果您取消選中其中之一的框,因此它不再被視為“過掃描”,它會更新以匹配當前value并跟隨更新到value,而仍然“過掃描”的那個則不會。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/333531.html
標籤:javascript 反应 表现
