懒渲染时组件状态丢失怎么办?
我在用 React 做一个长列表,为了性能用了懒渲染(比如只渲染可视区域的项)。但发现滚动回来后,之前输入过内容的表单项变空了,状态没了。
我试过把状态提到父组件,但数据量太大,维护起来很麻烦。有没有办法在懒渲染的同时保留组件内部状态?比如用 React.memo 或者其他方式?
const ListItem = ({ id, isVisible }) => {
const [inputValue, setInputValue] = useState('');
if (!isVisible) return null;
return <input value={inputValue} onChange={e => setInputValue(e.target.value)} />;
};
useRef来保存每个组件的状态,而不是依赖于 React 自己的 state 管理机制。首先我们要理解为什么原来的方法会失效:当组件被卸载时,它的状态也会被销毁。懒渲染的本质就是根据可视区域动态挂载和卸载组件,所以状态自然就丢失了。
这里有个解决方案:
需要注意的是,这里我们用
defaultValue而不是value,因为后者会让输入框变成受控组件,反而会影响性能。通过直接操作 DOM 元素的方式,可以避免重新渲染带来的性能开销。如果数据量特别大,还可以考虑把所有的状态存到一个全局对象中,以 id 作为 key。这样就不需要在父组件维护大量的状态了。
这种方法虽然看起来有点 hacky,但在实际项目中非常有效,特别是在处理大量表单元素的时候。当然,这种方案也有缺点,比如失去了 React 的单向数据流特性,可能会让代码更难维护。所以在使用时需要权衡利弊。