是否有延迟React组件更新的方法?



我们有一个大的网格渲染许多昂贵的组件。为了减少页面上的负载,我们使用了一个可视化的列表,在任何给定的时刻只呈现可见的部分。这意味着每当有人滚动时,就会有白色的闪烁,因为之前在可见区域之外的组件第一次渲染。

为了解决这个问题,我们可以定义一个"overscan"区域-在滚动上立即可见的可见区域周围渲染的项目数量。不幸的是,这意味着这些组件现在与页面状态一起更新,在我们的例子中,对于任何合理数量的监视来说,这都是一个昂贵的操作。

我在想解决这个问题的一种方法是将可见区域之外的组件的更新/渲染生命周期推迟到调用堆栈清除时,利用setTimeout,或者可能使用requestIdleCallback。我没能在React 16/17中找到这样做的方法-有什么想法吗?

你可以给组件一个属性,告诉他们是否在overcan中,如果inOverscan和当前的道具都是true,那么shouldComponentUpdate返回false(或者如果使用函数组件,如果inOverscan和当前的道具都是true,那么React.memo的比较函数将返回true)。

下面是一个例子:

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不会重新渲染Example1Example2。但如果你在其中一个的方框中打勾它就不会被认为是在overscan中不再,它更新以匹配当前的value,并遵循value的更新,而仍然在overscan"没有。

相关内容

  • 没有找到相关文章

最新更新