在Redux Reducer中更新嵌套对象的技术求助
Hey there! Let's work through this step by step to get your ingredient management app up and running. First, I spot a critical issue in your type definitions that's definitely throwing things off, then we'll tackle the reducer logic for updating that nested array state.
Step 1: Fix Action Type Constants
Right now, your ADD and DELETE constants both use the same string value "INGREDIENT"—Redux won't be able to tell your add and delete actions apart! Let's fix that first:
// Updated types.ts export interface Mytype { a: number; b: number; c: number; d: number; } export interface Mytype2 { Mytypes: Mytype[]; } // Use unique action type strings export const ADD_INGREDIENT = "INGREDIENT_ADD"; export const DELETE_INGREDIENT = "INGREDIENT_DELETE"; interface AddIngredientAction { type: typeof ADD_INGREDIENT; payload: Mytype; // Renamed from aName for clarity, but you can keep it if you prefer } interface DeleteIngredientAction { type: typeof DELETE_INGREDIENT; payload: Mytype; // Assuming we're passing the ingredient to delete } export type OrderActionTypes = AddIngredientAction | DeleteIngredientAction;
I renamed aName to payload since that's the standard Redux convention for action data, but feel free to stick with aName if that makes more sense for your codebase—just be consistent!
Step 2: Implement the Reducer with Immutable Updates
Redux requires immutable state updates, which means you can't modify the existing state directly. For nested arrays like Mytypes, we'll create new copies of the state and array instead of mutating them.
Here's how your reducer should look:
// ingredientReducer.ts import { Mytype2, OrderActionTypes, ADD_INGREDIENT, DELETE_INGREDIENT } from './types'; // Define your initial state const initialState: Mytype2 = { Mytypes: [] }; const ingredientReducer = (state = initialState, action: OrderActionTypes): Mytype2 => { switch(action.type) { case ADD_INGREDIENT: // Return a new state object with the new ingredient added to the array return { ...state, Mytypes: [...state.Mytypes, action.payload] }; case DELETE_INGREDIENT: // Filter out the ingredient to delete—here we're matching by the `a` property as the unique ID // Adjust this to match whatever unique identifier you use for your ingredients! return { ...state, Mytypes: state.Mytypes.filter(ingredient => ingredient.a !== action.payload.a) }; default: return state; } }; export default ingredientReducer;
Key Notes:
- Adding Ingredients: We use the spread operator (
...) to create a copy of the existingMytypesarray, then append the new ingredient to the end. This ensures we don't mutate the original array. - Deleting Ingredients: The
filtermethod returns a new array with all elements that don't match the ingredient we want to delete. I assumedingredient.ais your unique ID—if you use a different property (likeidor another field), just swap that out. - Immutable Updates: Always return a new state object instead of modifying
statedirectly. This is crucial for Redux to detect state changes and trigger re-renders.
Step 3: Verify Your Actions
Make sure your action creators are dispatching the correct types and payloads. For example:
// actionCreators.ts import { ADD_INGREDIENT, DELETE_INGREDIENT, Mytype, OrderActionTypes } from './types'; export const addIngredient = (ingredient: Mytype): OrderActionTypes => ({ type: ADD_INGREDIENT, payload: ingredient }); export const deleteIngredient = (ingredient: Mytype): OrderActionTypes => ({ type: DELETE_INGREDIENT, payload: ingredient });
That should do it! With these fixes, your reducer will correctly update the nested array state for adding and deleting ingredients.
内容的提问来源于stack exchange,提问作者Errand

