如何从Reducer中删除条目/如何返回新状态?(React/Redux)

Pet*_*ias 1 javascript reactjs redux react-redux

默认情况下,我的reducer返回此值(它来自教程):

return [
        {
            id: 1,
            first: "Bucky",
            last: "Roberts",
            age: 71,
            description: "Bucky is a React developer and YouTuber",
            thumbnail: "http://i.imgur.com/7yUvePI.jpg"
        },
        {
            id: 2,
            first: "Joby",
            last: "Wasilenko",
            age: 27,
            description: "Joby loves the Packers, cheese, and turtles.",
            thumbnail: "http://i.imgur.com/52xRlm8.png"
        },
        {
            id: 3,
            first: "Madison",
            last: "Williams",
            age: 24,
            description: "Madi likes her dog but it is really annoying.",
            thumbnail: "http://i.imgur.com/4EMtxHB.png"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

我现在希望能够从此"列表"中删除用户条目.所以我继续构建了一个删除用户动作创建者等,所以除了上面的数据之外,现在还有这个代码:

switch (action.type) {
    case 'USER_DELETED':
        console.log("Hello from reducer-users");
        let newState = Object.assign({}, state, );
        // console.log(newState == state);
        // console.log(newState.users == state.users)
        // delete newState.users;
        return newState;
        break;
}
Run Code Online (Sandbox Code Playgroud)

我们的想法是,如果有人单击"删除用户",则会调用此函数并返回一个新状态,并删除相应的用户.它也可以在调用函数的意义上工作(显示console.log).但是,我现在不确定如何从此列表中删除用户?我知道我需要复制当前状态,然后从副本中删除用户,然后返回副本,使其成为新状态.它是否正确?如果是这样,我不知道究竟是怎么回事.如果我尝试执行上面写的,这只是stackoverflow写的东西,我得到一个错误:

user-list.js?1cc2:11 Uncaught TypeError:this.props.users.map不是函数(...)renderList @ user-list.js?1cc2:11render @?d41d:33(匿名函数)@ReactCompositeComponent.js ?CD59:793measureLifeCyclePerf @ ReactCompositeComponent.js CD59:74_renderValidatedComponentWithoutOwnerOrContext @ ReactCompositeComponent.js CD59:??792_renderValidatedComponent @ ReactCompositeComponent.js CD59:819_updateRenderedComponent @ ReactCompositeComponent.js CD59:743_performComponentUpdate @ ReactCompositeComponent.js CD59:??721updateComponent @ ReactCompositeComponent.js CD59 :?642receiveComponent @ ReactCompositeComponent.js CD59:544receiveComponent @ ReactReconciler.js 6bfa:??126_updateRenderedComponent @ ReactCompositeComponent.js CD59:751_performComponentUpdate @ ReactCompositeComponent.js CD59:??721updateComponent @ ReactCompositeComponent.js CD59:642performUpdateIfNecessary @ ReactCompositeComponent.js CD59:558performUpdateIfNecessary @ ReactReconciler.js?6bfa:158runBatchedUpdates @ ReactUpdates.js?ce09:151perform @Transaction.js?6dff:138perform @Transaction.js?6dff:138perform @ ReactUpdates.js?ce09:90flushBatchedUpdates @ ReactUpdates.js?ce09:173closeAll @Transaction.js?6dff:204perform @Transaction.js?6dff: 151batchedUpdates @ ReactDefaultBatchingStrategy.js?ef70:63batchedUpdates @ ReactUpdates.js?ce09:98dispatchEvent @ ReactEventListener.js?2365:150

这是整个reducers文件:

/*
 * The users reducer will always return an array of users no matter what
 * You need to return something, so if there are no users then just return an empty array
 * */
export default function (state = null, action) {

    switch (action.type) {
        case 'USER_DELETED':
            console.log("Hello from reducer-users");

            //let newState = Object.assign([{}], state);
            // return newState;

            return state.filter(user => user.id !== action.userIdToDelete);
            console.log("UNTIL HERE");
            // console.log(newState.users == state.users)
            // delete newState.users;
            // return ([{
            //     id: 5,
            //     first: "Bucky",
            //     last: "Roberts",
            //     age: 71,
            //     description: "Bucky is a React developer and YouTuber",
            //     thumbnail: "http://i.imgur.com/7yUvePI.jpg"
            // }]);
            break;
            console.log("UNTIL HERE2222");
    }
    return [
        {
            id: 1,
            first: "Bucky",
            last: "Roberts",
            age: 71,
            description: "Bucky is a React developer and YouTuber",
            thumbnail: "http://i.imgur.com/7yUvePI.jpg"
        },
        {
            id: 2,
            first: "Joby",
            last: "Wasilenko",
            age: 27,
            description: "Joby loves the Packers, cheese, and turtles.",
            thumbnail: "http://i.imgur.com/52xRlm8.png"
        },
        {
            id: 3,
            first: "Madison",
            last: "Williams",
            age: 24,
            description: "Madi likes her dog but it is really annoying.",
            thumbnail: "http://i.imgur.com/4EMtxHB.png"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

fab*_*tto 5

你说你的减速器应该返回一个新的状态副本,而不是改变现有的副本.这种方法有一些非常好的好处(见这里:http://redux.js.org/docs/Glossary.html#reducer)

假设此reducer管理的状态是一个数组,要从列表中删除用户,您可以执行以下操作:

switch (action.type) {
    case 'USER_DELETED':
        return state.filter(user => user.id !== action.userIdToDelete);
}
Run Code Online (Sandbox Code Playgroud)

关键点在于Array.filter返回一个新的数组,该数组将回调应用于每个元素,决定保留/过滤哪个元素,它不会改变原始数组.查看这里的文档https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

您可能会尝试使用Array.splice(https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)但在这种情况下这是错误的,因为splice"更改了通过删除现有元素和/或添加新元素来获取数组的内容.",所以它确实改变了原始元素.

请注意,您需要传入userIdToDelete操作有效内容.

此外,您不需要,break因为您已经在使用return.

至于确切的原因您发布的错误,问题是,在目前的减速是不是返回对象的数组:let newState = Object.assign({}, state, ); 那么,在某处你的组件你是从国家阅读和你想叫map上你的状态,不再是一个数组(因此没有map为其定义方法)this.props.users

另一个建议是:

我真的建议你开始在reducers中使用普通的Js,总是要小心改变对象的方法.在你知道自己在做什么之后,有时在Js中使用不可变数据结构可能会很笨拙,所以你可以开始考虑使用这些库来减轻更复杂场景的痛苦(但只有在你确实需要的时候),按复杂程度排序(显然在我看来):