数据模型:这是一大堆食谱,每个食谱包含另一组成分。我希望允许用户勾选" (成分从阵列中除去)成分,因为他们购买/获得它们。
[
...
{
"title": "Recipe 1"
"ingredients": [
{ "title": "Flour", "measurement": "300g" },
{ "title": "Sesame Seeds", "measurement": "1 Tblsp" }
]
},
...
]
当前的Psuedo组件树:
// RecipeList is my "HOC" (higher-order component) and contains all the functions/data required for the rest of the tree, and simply passes them down as props. This is `connect()`ed to the store here.
<RecipeList>
// Map on the highest level array to display a <Recipe> component for each
<Recipe data={recipe[mappedIndex]}>
// Map on each ingredient to create a list item for each
<RecipeIngredient data={recipe[mappedIndex].ingredient[mappedIndex]>
<IngredientCheckBox onChange={ //remove this ingredient from the array } />
</RecipeIngredient>
</Recipe>
</RecipeList>
上述所有情况都很好,数据显示的确切方式如何。
然而,这是主要问题,当涉及到onChange
时,我调用了一个操作,COMPLETE_INGREDIENT
基本上将其从ingredients
数组中移除(我看到它在运作中,使用redux-logger
next-state
不包含它。)
不幸的是,我的组件不会重新渲染。它不再在阵列中,但仍显示在屏幕上。我理解这可能是以下原因之一:
connect()
只比浅比较状态,因此它不会触发重新渲染,因为它是数组中的值,在数组中对象的属性内。connect()
距离操作太远了,应该在更深的组件级别重新connect()
,比如说<Recipe>
组件,只将它附加到商店的一部分它关心的问题(甚至可能是<RecipeIngredient>
)。slice()
和各种各样,我仍然无法重新渲染编辑:我的行动减速机COMPLETE_INGREDIENT
。我理解这可能是问题,因为它直接改变了国家。如此深刻改变国家的正确方法是什么?
case COMPLETE_INGREDIENT:
// state is from a level above the recipe's, that contains a timestamp etc
state.recipes[action.payload.recipeIndex].ingredients.splice(action.payload.ingredientIndex, 1)
return Object.assign({
...state
})
答案 0 :(得分:1)
编辑:我的动作减速器COMPLETE_INGREDIENT。我明白这可能 是问题,因为它直接改变了国家。会是什么 如此深刻改变国家的正确方法?
是的,你正在用Object.assign改变状态。作为第一个参数,它应该有新的Object来复制值并返回:
return Object.assign({}, {
...state
})
根据你的代码,我创建了更新函数,我可能会创建:
case COMPLETE_INGREDIENT: {
const { recipeIndex, ingregientIndex } = action.payload;
const recipesListCopy = [...state.recipes];
const recipeCopy = {
...recipesListCopy[recipeIndex],
ingredients: recipesListCopy[recipeIndex].ingredients.filter(
(e, index) => index !== ingredientIndex
)
};
recipesListCopy[recipeIndex] = recipeCopy;
return {
...state,
recipes: recipesListCopy
};
}
编辑:
基于您的评论 - “如果配料阵列现在为空,则从顶级配方数组中删除配方”
case COMPLETE_INGREDIENT: {
const { recipeIndex, ingregientIndex } = action.payload;
const recipesListCopy = [...state.recipes];
const updatedIngredientsList = recipesListCopy[recipeIndex].ingredients.filter(
(e, index) => index !== ingredientIndex
);
if(updatedIngredientsList.length > 0) {
// update ingredients
const recipeCopy = {
...recipesListCopy[recipeIndex],
ingredients: updatedIngredientsList
};
recipesListCopy[recipeIndex] = recipeCopy;
} else {
// remove recipe because no igridients
recipesListCopy.splice(recipeIndex, 1);
}
return {
...state,
recipes: recipesListCopy
};
}
答案 1 :(得分:1)
这里的问题在于改变现有的状态
case COMPLETE_INGREDIENT:
// state is from a level above the recipe's, that contains a timestamp etc
state.recipes[action.payload.recipeIndex].ingredients.splice(action.payload.ingredientIndex, 1)
return Object.assign({
...state
})
方法splice
更改现有数组,但您需要创建新数组。这是示例
const obj = { a: { b: 5 } };
const copyObj = { ...obj };
copyObj.a.b = 1;
console.log(obj.a.b); // 1
console.log(copyObj.a.b); // 1
您已复制state
个对象,但ingredients
数组保持不变。所以你需要复制数组。
case COMPLETE_INGREDIENT:
return {
...state,
recipes: state.recipes.map(
(item, index) =>
index === action.payload.recipeIndex
? { ...item, ingredients: item.ingredients.filter((item, index) => index !== action.payload.ingredientIndex) }
: item
),
};