javascript - Redux 未正确更新状态——尽管在之前的行中添加了一个对象,但状态仍为空数组
问题描述
我正在尝试使用通常的做法更新我的 React Redux 状态。您将当前状态不变地复制到返回函数中,然后覆盖将具有新值的属性。
我的预期结果是
state.copy
更新到
[
{ webCopy: "", id: 0 },
{ webCopy: "", id: 1 }
]
不幸的是,尽管将复制值作为内部包含 JS 对象的新数组返回,但它是一个空数组。
我试过查看 StackOverflow 搜索结果,"react redux state not updating correctly"
但似乎没有一个搜索结果符合我的情况。
在我的应用程序中,我什至检查过:仅
case actionTypes.ADD_COMPONENT
(reducer 中的第一个)在应用程序的这一部分激活。它实际上是一个按钮点击触发
ADD_COMPONENT
在其自己的。任何其他减速器都没有任何活动可以用空[]
数组覆盖我的状态。
为什么我最后会得到一个空数组case actionTypes.ADD_COMPONENT
?
我的console.log()
语句甚至显示一个 JavaScript 对象是newCopy
RIGHT BEFORE I RETURN a new state 的值。
所以这里是 reducer.js。我已经上传了 COMPLETE 减速器,而不是仅仅case actionTypes.ADD_COMPONENT
在发生错误的地方:
import * as actionTypes from "./constants";
let component = "";
let idIteration = null;
let stateArray = [];
let tempCopy = [];
const initialState = {
components: [],
uniqueIdCounter: 0,
currentPage: 1,
copy: [],
siteURL: "/salespage/"
};
const reducer = (state = initialState, action) => {
switch (action.type) {
// you can probably ignore everything outside of this switch statement
// this is the important switch statement
case actionTypes.ADD_COMPONENT:
stateArray = [...state.components];
console.log("state:", state);
console.log("State Copy:", state.copy);
component = action.payload[0]; // will be "Header", "Headline", "Text Area", "Image", "Email Field", "Footer"
if (component === "Header") {
// append "Header" component to the beginning of the list
stateArray.unshift({
type: component,
id: state.uniqueIdCounter
});
} else {
// push component to the end of the list
stateArray.push({
type: component,
id: state.uniqueIdCounter
});
}
idIteration = state.uniqueIdCounter + 1;
// SEND HELP. How could state.copy possibly be anything other than a JS object after these lines?
let newCopy = [...state.copy];
newCopy.push({ webCopy: "", id: action.payload[1] });
console.log("TTTTTTTTT", newCopy);
return {
...state,
components: stateArray,
uniqueIdCounter: idIteration,
copy: newCopy // why doesn't this update the array to contain newCopy? it should.
};
// i don't know how any of this could possibly cause my state.copy to be equal to []
case actionTypes.SET_NEW:
console.log("Activating SET_NEW");
// uploads the newly reordered set of components to state
let uploadNewOrder = [...action.payload];
return {
...state,
components: uploadNewOrder
};
case actionTypes.DEL:
console.log("activating DEL");
// uploads the state less the deleted item
let uploadShortened = [...action.payload];
return {
...state,
components: uploadShortened
};
case actionTypes.PAGE_CHANGE:
console.log("activating PAGE_CHANGE");
stateArray = [...state.components];
return {
...state,
// action.payload is set in each page's ComponentDidMount()
currentPage: action.payload
};
case actionTypes.NEW_VAR:
console.log("activating NEW_VAR");
// case "NEW_VAR" fires from Customize's renderStateComponents()
stateArray = [...state.components];
tempCopy = Object.assign([], state.copy); // avoids the TypeError bug with [...state.copy]
// push an empty copy datapoint to state with a unique id to use in identifying which copy goes where in interface
let newInputFieldNumber = { webCopy: "", id: action.payload };
tempCopy.push(newInputFieldNumber);
return {
...state,
components: stateArray,
copy: tempCopy
};
case actionTypes.ADD_COPY:
console.log("activating ADD_COPY");
tempCopy = [...state.copy]; // immutably copy state.copy
let textToAdd = action.payload[0];
let indexToFind = action.payload[1];
for (let i = 0; i < tempCopy.length; i++) {
if (tempCopy[i].id === indexToFind) {
// Modify the JS object linked to the appropriate input field
tempCopy[i] = { webCopy: textToAdd, id: indexToFind };
}
}
return {
...state,
components: stateArray,
copy: tempCopy
};
case actionTypes.SET_URL:
console.log("activating SET_URL");
stateArray = [...state.components];
// TODO: handle cases like user entered www.etc.com and https://www.test.com
let domain = action.payload;
const notAllowed = [
"https://www.",
"www.",
".",
"www",
"com",
"net",
"org",
".com",
".net",
".org"
];
for (let i = 0; i < notAllowed.length; i++) {
if (domain.includes(notAllowed[i])) {
domain = domain.replace(notAllowed[i], "");
}
}
return {
...state,
components: stateArray,
siteURL: "/salespage/" + domain
};
default:
return state;
}
};
export default reducer;
有什么建议可以尝试吗?我尝试将此案例添加到我的减速器并在之后的行中激活它,.ADD_COMPONENT
它仍然产生一个空数组:
case actionTypes.PREP_COPY:
let prepCopy = [...state.copy];
prepCopy.push({ webCopy: "", id: action.payload });
return {
...state,
copy: prepCopy
};
我给了有问题的变量 ,newCopy
一个唯一的名称,以便不使用全局范围。万一这很重要。
我还能显示什么其他代码?只有 reducer 可以影响 Redux 状态,除了 .ADD_COMPONENT 和(现在).PREP_COPY 之外没有其他代码在运行
编辑:根据建议,我尝试在返回状态时将扩展运算符与我的变量一起使用。如果我仅在 BOTH Reducer Actions 中使用 Spread 运算符,则该代码现在可以工作。仅在其中一个中使用它仍然会产生一个空数组。像这样:
const reducer = (state = initialState, action) => {
switch (action.type) {
case actionTypes.ADD_COMPONENT:
// edited out some code...
let newCopy = [...state.copy];
newCopy.push({ webCopy: "", id: action.payload[1] });
console.log("newCopy", newCopy);
return {
...state,
components: stateArray,
uniqueIdCounter: idIteration,
copy: [...newCopy]
};
case actionTypes.PREP_COPY:
console.log("State.copy:", state.copy);
let prepCopy = [...state.copy];
prepCopy.push({ webCopy: "", id: action.payload });
console.log("PREPCOPY:", prepCopy);
return {
...state,
copy: [...prepCopy]
};
所以要么我同时使用这两个动作,要么nada。从字面上看:当我同时使用两者时,每个周期都会添加两个 JS 对象。当我只使用一个时,每个周期会添加 0 个 JS 对象。呜。
比如,我应该向 React 的团队报告错误吗?
第二次编辑:这是一个完整的代码沙箱。单击按钮时检查 console.log 语句https://codesandbox.io/s/lucid-heisenberg-iczww
解决方案
您是否尝试过将副本作为新数组返回?它以前为我解决了问题
您可以只使用扩展运算符来创建它:
return {
...state,
components: stateArray,
uniqueIdCounter: idIteration,
copy: [...newCopy]
};
另一种类似的方法将消除将值推送到临时变量的需要:
return {
...state,
components: stateArray,
uniqueIdCounter: idIteration,
copy: [...state.copy, { webCopy: "", id: action.payload[1] }]
};
推荐阅读
- reactjs - 使用 React 无法从 Firestore 中删除
- java - 使用 Apache POI 从 Word 文档中获取文本框段落
- azure-devops - 具有动态 azureSubscription 的 DevOps Pipeline AzureCLI@2
- sql - 找到某个字符后在一个组中计数之前和之后
- bash - 如何保存包含空间和参数作为变量的可执行文件的路径?
- css - 我的边框底部未显示在 Vuetify 中
- sql-server - SQL Server 中的表更新减慢子查询中的索引查找
- c# - C#:为嵌入文档中的属性创建索引
- ios - 当我们滑动时,单元格保持突出显示并以交互方式取消突出显示
- pyspark - 如何在 pyspark 中捕获错误