英文:
Error: Invariant failed: A state mutation was detected between dispatches in next js
问题
当我尝试从前端更改状态时,错误显示...
错误:不变性失败:在分派之间检测到状态突变,在路径 'products.productAttributes.0.attribute' 中。这可能会导致不正确的行为。 (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)
我的Reducer:
import {
GET_PRODUCTS_BY_QUERY,
GET_PRODUCT_BY_ID,
GET_PRODUCTS,
PRODUCT_DATA_ON_PROGRESS,
PRODUCT_DATA_SUBMIT_PROGRESS,
OPEN_PRODUCT_SIDEBAR,
BIND_PRODUCT_BASIC_INFO,
BIND_PRODUCT_ATTRIBUTES,
} from '../action-types';
import { ProductBasicInfoModal, attributes } from '../model';
const initialState = {
dataProgress: false,
submitProductDataProgress: false,
openProductSidebar: false,
products: [],
productAttributes: attributes,
product: ProductBasicInfoModal,
total: 1,
queryParams: {},
queryObj: {},
};
const productReducers = (state = initialState, action) => {
switch (action.type) {
case GET_PRODUCTS_BY_QUERY:
return {
...state,
products: action.products,
total: action.total,
queryParams: action.queryParams,
queryObj: action.queryObj,
};
case GET_PRODUCT_BY_ID:
return {
...state,
product: action.product,
};
case BIND_PRODUCT_BASIC_INFO:
return {
...state,
product: action.product,
};
case BIND_PRODUCT_ATTRIBUTES:
return {
...state,
productAttributes: action.attributes,
};
case PRODUCT_DATA_ON_PROGRESS:
return {
...state,
dataProgress: action.dataProgress,
};
case PRODUCT_DATA_SUBMIT_PROGRESS:
return {
...state,
submitProductDataProgress: action.submitProductDataProgress,
};
case OPEN_PRODUCT_SIDEBAR:
return {
...state,
openProductSidebar: action.openProductSidebar,
};
default:
return state;
}
};
export default productReducers;
然后我的Action:
export const bindProductAttributes = (data) => (dispatch) => {
dispatch({
type: BIND_PRODUCT_ATTRIBUTES,
attributes: data,
});
};
这是我的组件函数:
const dispatch = useDispatch();
const { product, productAttributes } = useSelector(
({ products }) => products
);
const handleDropdownOChange = (data, e, rowId) => {
const { name } = e;
const attributes = [...productAttributes].map((att) => {
if (att.id === rowId) {
att[name] = data;
}
return att;
});
dispatch(bindProductAttributes(attributes));
};
当触发动作 handleDropdownOChange 时,我遇到了问题!
请帮助我!
英文:
When I try to change the state from the front-end, the error shows...
Error: Invariant failed: A state mutation was detected between dispatches, in the path 'products.productAttributes.0.attribute'. This may cause incorrect behavior. (https://redux.js.org/style-guide/style-guide#do-not-mutate-state)
My Reducer :
import {
GET_PRODUCTS_BY_QUERY,
GET_PRODUCT_BY_ID,
GET_PRODUCTS,
PRODUCT_DATA_ON_PROGRESS,
PRODUCT_DATA_SUBMIT_PROGRESS,
OPEN_PRODUCT_SIDEBAR,
BIND_PRODUCT_BASIC_INFO,
BIND_PRODUCT_ATTRIBUTES,
} from '../action-types';
import { ProductBasicInfoModal, attributes } from '../model';
const initialState = {
dataProgress: false,
submitProductDataProgress: false,
openProductSidebar: false,
products: [],
productAttributes: attributes,
product: ProductBasicInfoModal,
total: 1,
queryParams: {},
queryObj: {},
};
const productReducers = (state = initialState, action) => {
switch (action.type) {
case GET_PRODUCTS_BY_QUERY:
return {
...state,
products: action.products,
total: action.total,
queryParams: action.queryParams,
queryObj: action.queryObj,
};
case GET_PRODUCT_BY_ID:
return {
...state,
product: action.product,
};
case BIND_PRODUCT_BASIC_INFO:
return {
...state,
product: action.product,
};
case BIND_PRODUCT_ATTRIBUTES:
return {
...state,
productAttributes: action.attributes,
};
case PRODUCT_DATA_ON_PROGRESS:
return {
...state,
dataProgress: action.dataProgress,
};
case PRODUCT_DATA_SUBMIT_PROGRESS:
return {
...state,
submitProductDataProgress: action.submitProductDataProgress,
};
case OPEN_PRODUCT_SIDEBAR:
return {
...state,
openProductSidebar: action.openProductSidebar,
};
default:
return state;
}
};
export default productReducers;
Then My Action:
export const bindProductAttributes = (data) => (dispatch) => {
dispatch({
type: BIND_PRODUCT_ATTRIBUTES,
attributes: data,
});
};
Here is my Component Function:
**
const dispatch = useDispatch();
const { product, productAttributes } = useSelector(
({ products }) => products
);
const handleDropdownOChange = (data, e, rowId) => {
const { name } = e;
const attributes = [...productAttributes].map((att) => {
if (att.id === rowId) {
att[name] = data;
}
return att;
});
dispatch(bindProductAttributes(attributes));
};
**
I faced the problem when the action handleDropdownOChange is fired!
Please Help me !
答案1
得分: 1
问题很可能出在 att[name] = data;
这一行。这会导致对 att
进行_变异_,而该变量最初来自Redux存储。不要这样做
在这里_最好的_解决方案是,改为派发一个可能包含行ID和数据的操作,然后让_减速器_来处理更新:
你还应该使用Redux Toolkit的createSlice
来编写该减速器。
这些要素一起将使管理更新变得更简单,并且消除了意外的变异问题。
英文:
The issue is most likely the line att[name] = data;
. This mutates att
, and that variable is an object that originally came from the Redux store. Don't do that
The best answer here is to instead dispatch an action that might contain the row ID and the data, and let the reducer take care of handling the update:
- https://redux.js.org/style-guide/#put-as-much-logic-as-possible-in-reducers
- https://redux.js.org/style-guide/#reducers-should-own-the-state-shape
You should also use Redux Toolkit's createSlice
to write that reducer.
Those pieces together will make it much simpler to manage the update, and eliminate the accidental mutation problem.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论