简体   繁体   English

React-window,如何防止 state 更改上的重新渲染列表?

[英]React-window, how to prevent rerendering list on state change?

This my code sandbox example: https://codesandbox.io/s/react-hooks-counter-demo-kevxp?file=/src/index.js这是我的代码沙箱示例: https://codesandbox.io/s/react-hooks-counter-demo-kevxp?file=/src/index.js

My problem is: The list will always rerendering on every state change inside the page so the scroll will always back to the top.我的问题是:该列表将始终在页面内的每个 state 更改上重新呈现,因此滚动将始终回到顶部。 I want to know why this happen, and how to prevent this behaviour even the state of the list have changes then keep the last scroll position of the list我想知道为什么会发生这种情况,以及如何防止这种行为,即使列表的 state 发生了变化,然后保留列表的最后一个滚动 position

Every time App renders, you are creating a brand new definition for the Example component.每次App呈现时,您都在为Example组件创建一个全新的定义。 It may do the same thing as the old one, but it's a new component.它可能与旧组件做同样的事情,但它是一个新组件。 So react compares the element from one render with the element of the next render and sees that they have different component types.因此,react 将来自一个渲染的元素与下一个渲染的元素进行比较,并查看它们具有不同的组件类型。 Thus, thus it is forced to unmount the old one and mount the new one, just as it would if you changed something from a <div> to a <span> .因此,它被迫卸载旧的并安装新的,就像您将某些东西从<div>更改为<span>一样。 The new one begins scrolled to 0.新的开始滚动到 0。

The solution to this is to create Example only once, outside of App.解决方案是在 App 之外只创建一次示例。

const Example = props => (
  <List
    className="List"
    height={80}
    itemCount={props.propsAbc.length}
    itemSize={20}
    width={300}
    itemData={{
      dataAbc: props.propsAbc
    }}
  >
    {({ index, style, data }) => (
      <div className={index % 2 ? "ListItemOdd" : "ListItemEven"} style={style}>
        {data.dataAbc[index]}
      </div>
    )}
  </List>
);

function App() {
  const [count, setCount] = useState(0);
  let [dataArray, setDataArray] = useState([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

  return (
    <div className="App">
      <h1>Scroll down the blue box, then click the button</h1>
      <h2>You clicked {count} times!</h2>

      <button onClick={() => setCount(count - 1)}>Decrement</button>
      <button onClick={() => setCount(count + 1)}>Increment</button>

      <div
        style={{ maxHeight: "80px", overflow: "äuto", background: "lightblue" }}
      >
        <Example propsAbc={dataArray} />
      </div>
    </div>
  );
}

https://codesandbox.io/s/react-hooks-counter-demo-qcjgj https://codesandbox.io/s/react-hooks-counter-demo-qcjgj

I don't think it's a react window problem.我不认为这是一个反应 window 问题。

A react component re-renders because there's a state change.由于 state 发生了更改,因此会重新渲染反应组件。 In this case, the state change is caused by setCount (when you click the increment button), which re-renders the entire component including Example.在这种情况下,state 更改是由 setCount 引起的(当您单击增量按钮时),它会重新渲染包括示例在内的整个组件。

If Example is its own component, the scroll position won't get refreshed, because it no longer depends on the count state.如果 Example 是它自己的组件,则滚动 position 不会被刷新,因为它不再依赖于计数 state。

A working sample here: https://codesandbox.io/s/react-hooks-counter-demo-hbek7?file=/src/index.js此处的工作示例: https://codesandbox.io/s/react-hooks-counter-demo-hbek7?file=/src/index.js

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM