I'm trying to create an app that will allow users to build a recipe and make changes to it. I'm using React Toolkit and Redux to manage the state.
Example state:
const ingredients = [
{
ingredientName: 'Flour',
ingredientMeasurement: 500,
ingredientUnit:'g',
ingredientMeasurementUpdate: 0,
},
{
ingredientName: 'Water',
ingredientMeasurement: 200,
ingredientUnit:'g',
ingredientMeasurementUpdate: 0,
},
{
ingredientName: 'Apples',
ingredientMeasurement: 350,
ingredientUnit:'g',
ingredientMeasurementUpdate: 0,
},
I have this slice for my ingredients. The updateFields is to add a new measurement and assign it to that ingredient.
const initialState = {
ingrediants: [],
};
export const ingredientsSlice = createSlice({
name: "ingredientList",
initialState,
reducers: {
addIngredients: (state, action) => {
state.ingrediants = [...state.ingrediants, action.payload];
},
removeIngrediants: (state, action) => {
state.ingrediants = state.ingrediants.filter(
(i) => i.id !== action.payload.id
);
},
updateFields: (state, action) => {
state.ingrediants = { ...state.ingrediants, ...action.payload };
},
},
});
export const { addIngredients, removeIngrediants, updateFields } = ingredientsSlice.actions;
export default ingredientsSlice.reducer;
I have this page that displays the list of ingredients:
const alteration = () => {
return (
<main className="h-screen flex">
<div className="relative h-full w-1/3 border-4">
<div className="absolute inset-y-0 left-0 w-80">
<h1>Hello </h1>
<RecipeList />
</div>
</div>
<div></div>
</main>
);
};
export default alteration;
Here is the component that I would like it to update the state and add a new measurement
export const RecipeList = memo(() => {
const ingredientList = useSelector(
(state) => state.ingredientList.ingrediants
);
const dispatch = useDispatch();
const [
ingredientMeasurementUpdate,
setIngrediantMeasurementUpdate,
] = useState();
const onFormSubmit = useCallback(
(e) => {
e.preventDefault();
dispatch(
updateFields({
ingredientMeasurementUpdate,
})
);
setIngrediantMeasurementUpdate("");
},
[ingredientMeasurementUpdate, dispatch]
);
return (
<div>
<div>
{ingredientList.map((ingredient) => (
<div
className="border-gray-800 border h-52 w-full"
key={ingredient.id}
>
{` ${ingredient.ingredientMeasurement}${ingredient.ingredientUnit} ${ingredient.ingredientName}`}{" "}
<form onSubmit={onFormSubmit}>
<fieldset>
<input
className="border-2"
type="text"
value={ingredientMeasurementUpdate}
id="ingrediantunit"
onChange={(e) =>
setIngrediantMeasurementUpdate(e.target.value)
}
></input>
</fieldset>
<fieldset>
<button type="submit">add</button>
</fieldset>
</form>
</div>
))}
</div>
</div>
);
});
I have another form that allows the user to add ingredients to their recipe
export const IngrediantsForm = memo(() => {
const dispatch = useDispatch();
const [ingredientName, setIngrediantName] = useState("");
const [ingredientMeasurement, setIngrediantMeasurement] = useState();
const [ingredientUnit, setIngrediantUnit] = useState("");
const onFormSubmit = useCallback(
(e) => {
e.preventDefault();
dispatch(
addIngredients({
ingredientName,
ingredientMeasurement,
ingredientUnit,
id: uuidV4(),
})
);
setIngrediantName("");
setIngrediantMeasurement("");
setIngrediantUnit("");
},
[ingredientName, ingredientMeasurement, ingredientUnit, dispatch]
);
return (
<form onSubmit={onFormSubmit}>
<fieldset>
<input
className="border-2"
type="text"
value={ingredientName}
id="ingrediantname"
onChange={(e) => setIngrediantName(e.target.value)}
></input>
</fieldset>
<fieldset>
<input
className="border-2"
type="number"
value={ingredientMeasurement}
id="ingrediantmeasurement"
onChange={(e) => setIngrediantMeasurement(e.target.value)}
></input>
</fieldset>
<fieldset>
<input
className="border-2"
type="text"
value={ingredientUnit}
id="ingrediantunit"
onChange={(e) => setIngrediantUnit(e.target.value)}
></input>
</fieldset>
<fieldset>
<button className="border-2" type="submit">
add
</button>
</fieldset>
</form>
);
});
I'm not entirely sure how to access the state (which is the list of ingredients) and then add another key/value to the object so that I have one key called ingredientMeasurement and another called ingredientMeasurementUpdate. The problem I believe is that it doesn't update the ingredientMeasurementUpdate on the right ingredient possibly because it doesn't know which one I need to update.
What I seem to get on Redux DevTools is this:
ingredientList: {
ingrediants: {
'0': {
ingredientName: 'Apples',
ingredientMeasurement: '100',
ingredientUnit: 'g',
ingredientMeasurementUpdate: 0,
id: '455ed39b-57b9-4351-98a7-5845cae676b5'
},
'1': {
ingredientName: 'Flour',
ingredientMeasurement: '650',
ingredientUnit: 'g',
ingredientMeasurementUpdate: 0,
id: 'e96349a1-e8ea-4cc6-aa68-6fbfc42ff87b'
},
ingredientMeasurementUpdate: '250'
}
}
in addIngredients use state.ingrediants.push(payload)
The problem is in your updateFields action you have to pass the particular ingrediant id in the payload to update the particular ingrediant in the array.
Change the whole code with the following code:
updateFields: (state, action) => {
let index=state.ingrediants.findIndex((i)=>i.id===action.payload.id);
if(index!=-1) {
state.ingrediants[index]={...action.payload}
}
},
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.