3

This my code sandbox example: 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. 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

My real name
  • 535
  • 1
  • 5
  • 17

2 Answers2

4

Every time App renders, you are creating a brand new definition for the Example component. 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. 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>. The new one begins scrolled to 0.

The solution to this is to create Example only once, outside of 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

Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
1

I don't think it's a react window problem.

A react component re-renders because there's a state change. In this case, the state change is caused by setCount (when you click the increment button), which re-renders the entire component including Example.

If Example is its own component, the scroll position won't get refreshed, because it no longer depends on the count state.

A working sample here: https://codesandbox.io/s/react-hooks-counter-demo-hbek7?file=/src/index.js

weiklr
  • 159
  • 1
  • 7