Redux从操作创建者返回新值时返回错误消息



我目前正在开发一个试用应用程序,允许用户对最佳轶事进行投票,当用户投票时,操作创建者应该返回一个新的排序对象数组。然而,我一直得到这个错误信息:

An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.

我对这个错误信息有点困惑因为我不知道我在哪里修改了原始状态因为我假设过滤器地图和不会扰乱国家的秩序。我哪里错了?下面是我的代码:

import _, { sortBy } from 'underscore';
import { createSlice, current } from '@reduxjs/toolkit';
const anecdotesAtStart = [
'If it hurts, do it more often',
'Adding manpower to a late software project makes it later!',
'The first 90 percent of the code accounts for the first 90 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.',
'Any fool can write code that a computer can understand. Good programmers write code that humans can understand.',
'Premature optimization is the root of all evil.',
'Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.'
]
const getId = () => (100000 * Math.random()).toFixed(0)
const asObject = (anecdote) => {
return {
content: anecdote,
id: getId(),
votes: 0
}
}
const initialState = anecdotesAtStart.map(asObject)
const anecdoteSlice = createSlice({
name: 'anecdote',
initialState,
reducers: {
createNotification(state, action) {
return action.payload;
},
increaseVote(state, action) {
const currentArray = state.filter(obj => obj.id === action.payload)
const newState = state.map(obj => {
// 👇️ if id equals 2 replace object
if (obj.id === currentArray[0].id) {
currentArray[0].votes += 1
return currentArray[0]
}
// 👇️ otherwise return object as is
return obj;
});
const sortedArray = _.sortBy(newState, 'votes')
return sortedArray
},
createAnecdote(state, action) {
const newAnecdote = action.payload
const initializedAnecdote = asObject(newAnecdote)
const updatedAnecdotes = state.concat(initializedAnecdote)
return updatedAnecdotes;
},
}})
export const { createNotification, increaseVote, createAnecdote} = anecdoteSlice.actions
export default anecdoteSlice.reducer

我相信错误发生在递增投票:

increaseVote(state, action) {
const currentArray = state.filter(obj => obj.id === action.payload)
const newState = state.map(obj => {
// 👇️ if id equals 2 replace object
if (obj.id === currentArray[0].id) {
currentArray[0].votes += 1
return currentArray[0]
}
// 👇️ otherwise return object as is
return obj;
});
const sortedArray = _.sortBy(newState, 'votes')
return sortedArray
},

我对这个错误消息感到困惑,因为我没有看到我在哪里修改了原始状态,因为我认为过滤器和映射不会扰乱状态。我哪里错了?

这个问题的答案

当你运行这行代码时,你的状态是一个对象数组,你认为filter()返回的是一个新数组,你是对的,但是引用类型的项被复制到新数组

因此,currentArray中的每个项都将指向原始数组中的项,如果您正在修改currentArray中的任何项,则更改也将反映在原始数组中。这个概念被称为浅拷贝

const currentArray = state.filter(obj => obj.id === action.payload)

浅拷贝->

对象的浅拷贝是指其属性与源对象的属性共享相同的引用(指向相同的底层值)。因此,当您更改源或副本时,可能也会导致其他对象也发生更改—因此,您可能会在无意中对源或副本造成意想不到的更改。这种行为与深度复制的行为形成对比,在深度复制中,源和副本是完全独立的。

例如,如果在一个名为copy的数组对象的浅拷贝中,copy[0]元素的值为{"list":["butter","flour"]},则执行copy[0]。List = ["oil","flour"],那么源对象中相应的元素也会改变——因为您选择性地更改了源对象和浅拷贝共享的对象的属性。

然而,如果你做了copy[0] = {"list":["oil","flour"]},那么源对象中相应的元素将不会改变——因为在这种情况下,你不仅仅是有选择地改变了与源对象共享的现有数组元素的属性;相反,你实际上是给copy[0]数组元素赋了一个全新的值,只是在浅拷贝中。

在JavaScript中,所有标准的内置对象复制操作(扩展语法、Array.prototype.concat()、Array.prototype.slice()、Array.from()、Object.assign()和Object.create())都创建浅拷贝而不是深拷贝。

引用→https://developer.mozilla.org/en-US/docs/Glossary/Shallow_copy

相关内容

  • 没有找到相关文章

最新更新