Shouldn't Redux prevent re-rendering?

前端 未结 2 1541
说谎
说谎 2021-01-01 07:26

I have a List component that displays multiple Item components. List gets its data from the Redux store.

When the store is up

相关标签:
2条回答
  • 2021-01-01 08:07

    A little bit of prior art (as Dan Abramov likes to say): Redux is a state management tool. It provides a HOC (connect), but that HOC is not responsible for component management. Redux does not manage your component's lifecycle in anyway: it provides a means to efficiently store and query data your app needs. It's largely influenced by the Om, a Clojurescript bridge to React. In fact, stores in redux very much resemble the atom data type in Clojure.

    Now, getting into the meat of your problem -- even if your data is exactly the same, and even if you did use shouldComponentUpdate, your component is still going to re-render. The reason is that Array.prototype.map always produces a new object on the heap. As a result they're not referentially equal. Some code to demonstrate this concept:

    const myArr = [1, 2, 3]
    const myArrCopy = myArr.map((n) => n);
    myArr === myArrCopy // false
    

    But if we use shallowEqual, we get a different result:

    const myArr = [1, 2, 3]
    const myArrCopy = myArr.map((n) => n);
    React.addons.shallowCompare(myArr, myArrCopy); // true
    

    Why is that? That's because shallowCompare checks for value equality, comparing each value in the arrays. However, shallowEquals contains a potential pitfall for the uninitiated:

    const myObject = { foo: 'bar' };
    const myObject2 = { foo: 'baar' };
    React.addons.shallowCompare(myObject, myObject2); // true
    

    Our two objects aren't the same, but shallowCompare returns true because it only compares the keys of its arguments. If that's good enough for you, you can simply extend React.PureComponent, which implements shouldComponentUpdate for you, and uses shallowCompare to compute equality of props and state.

    Enter Immutable.js. This does away with the need for shallowCompare entirely. Consider the following:

    const myList = Immutable.List([1, 2, 3]);
    const myListCopy = myList.map((n) => n);
    myList.equals(myListCopy) // true
    

    Internally, Immutable shares data, and can very efficiently compare data structures for deep equality. That being said, Immutable comes with trade-offs: data structures become much more opaque and can be more difficult to debug. All in all, I hope this answers your question. JSBin here: https://jsbin.com/suhujalovi/edit?html,js,console

    0 讨论(0)
  • 2021-01-01 08:30
    {items.map((item, index) => <Item key={index} name={item.name} />)}
    

    This line make always a new Array in the parent component, producing 'new' Item components every time

    0 讨论(0)
提交回复
热议问题