Redux:无法弄清楚为什么ownProps与状态不同步

Jam*_*yer 7 reactjs redux

为什么?https://codepen.io/jamesplayer/project/editor/AjWvBb

我正在构建一个大的Redux应用程序并且设法产生一个错误,其中列表项正在传递一个不再存在于商店中的id,所以当它从商店获取完整对象时它无法找到它,导致这里显然修复了react-redux中的错误

要重现需要一个非常特定的组件序列来进行一些安装,调度,连接和渲染,所以我在这个codepen中创建了一个问题的例子:https://codepen.io/jamesplayer/project/editor/AjWvBb

似乎调整此设置中的大多数内容可以修复错误,但我不确定为什么这个特定的设置会产生问题.如果有人能够向我解释为什么这个特定的事件顺序会产生错误,我真的很感激它,我一直试图深入了解它的底部.

基本结构如下:

<Parent>

    <Page1 "I dispatch an action to clear out the list items every time I mount,
            then re-populate them after about 500ms">

        <Page1Wrapper "I'm connected to the store. I get an update when my child 
                       Page1Child1 mounts">

            <Child1 "I dispatch an action when I mount that can affect Page1Wrapper">

            <Child2 "I'm connected to the store, though in this example I don't receive any updates that would cause a 
                     re-render">

                <List "I get a list of ids from the store. I pass each id to a ListItem">

                    <ListItem "I'm connected to the store. I get passed an id from 
                               List and fetch the whole listItem object">

    <Page2 "I don't do much, but going from page1 to page2 and then back to page1 is 
            a good way to reproduce the error">
Run Code Online (Sandbox Code Playgroud)

riw*_*iwu 3

问题

在 中ConnectedListstate.listItems不为空,因此List呈现 的实例ConnectedListItem

但是,在可以从商店获取它之前state.listItems已被操作清除,这导致它无法从现在清空的 中找到任何匹配项。CLEAR_LIST_ITEMSConnectedListItemstate.listItems

这个错误需要非常精确的时间来重现,这可能解释了为什么改变周围的东西可以修复它(例如,如果渲染ConnectedListItem之前完成CLEAR_LIST_ITEMS)。

解决方案

如果您提供默认值listItem(例如const ListItem = ({ listItem = {} })),它将防止崩溃并ConnectedList使用更新后的state.listItems.

我建议不要这样做state.listItems.map(listItem => listItem.id)connect因为它会导致组件始终重新渲染,因为即使state.listItems没有更改也会构造不同的数组。映射应该在组件中完成或通过重新选择来完成。

一种更简洁的方法是将整个项目传递给ListItem,从而无需ListItem连接到商店:

const ListItem = ({ item }) => <li>{item.text}</li>;

const List = ({ listItems }) => (
  <div style={{ backgroundColor: 'lightgreen' }} className="border">
    I'm List and I get a list of ids from the store. I pass each id to a ListItem.
    <ul>{listItems.map(item => <ListItem key={item.id} item={item} />)}</ul>
  </div>
);

const ConnectedList = connect(state => ({
  listItems: state.listItems,
}))(List);
Run Code Online (Sandbox Code Playgroud)

编辑417121z17