如何在Redux Reducer中添加对象?Next.js多表单输入问题
Let's fix your Redux state handling to match the logic you already have working with useState. The core issue here is that your current reducer isn't set up to handle individual input updates the way your local state does, and your dispatch call was passing incorrect data.
Here's what you need to change:
1. Update Your Redux Slice to Handle Item Updates
Instead of a generic setArr reducer that tries to push to the array, create a reducer that mimics the exact logic from your useState updater. Redux Toolkit uses Immer under the hood, so you can safely modify the state directly (it handles immutable updates for you).
import { createSlice } from "@reduxjs/toolkit"; const initialState = { arr: [] }; export const arrSlice = createSlice({ name: "arrS", initialState, reducers: { // This reducer handles adding/updating/removing items based on input value updateArrItem: (state, action) => { const { name, val } = action.payload; const existingItemIndex = state.arr.findIndex(item => item.name === name); if (val === "") { // Remove the item if the input is cleared and it exists if (existingItemIndex !== -1) { state.arr.splice(existingItemIndex, 1); } } else { if (existingItemIndex !== -1) { // Update the existing item's value state.arr[existingItemIndex] = { name, val }; } else { // Add a new item if it doesn't exist state.arr.push({ name, val }); } } }, // Optional: Keep this if you need to set the entire array at once (e.g., initialization) setArr: (state, action) => { state.arr = action.payload; } } }); export const { updateArrItem, setArr } = arrSlice.actions; export default arrSlice.reducer;
2. Fix the Dispatch Call in Your Component
Your original dispatch(setRooms(...amen)) was incorrect because you were spreading the array as individual arguments, but your reducer expected a single payload. Instead, dispatch the new updateArrItem action with the input's name and value directly.
You can also remove the local useState if you want to rely entirely on Redux for state management (no need to sync both):
import { useSelector, useDispatch } from 'react-redux'; import { updateArrItem } from '../path/to/your/arrSlice'; // Adjust the path to your slice // ... const dispatch = useDispatch(); // Get the current state from Redux const amen = useSelector(state => state.arrS.arr); // Make sure this matches your store's structure const updateVal = (e, type) => { const inputValue = e.target.value; // Dispatch the action with the name of the amenity and its value dispatch(updateArrItem({ name: type, val: inputValue })); };
Why This Works:
- The
updateArrItemreducer replicates the exact logic from youruseStateupdater: it checks if the item exists, updates it if it does, adds it if it doesn't, and removes it if the input is cleared. - Redux Toolkit's Immer integration lets you write "mutating" code that gets converted to immutable updates under the hood, so you don't have to manually spread arrays like you do with vanilla React state.
- You no longer need to sync local state with Redux—your component can directly read the state from Redux and dispatch actions to update it.
What Was Wrong Before:
- Your original
setArrreducer tried to spreadaction.payloadinto the array, butaction.payloadwas a single object (not an iterable array), hence theTypeError: action.payload is not iterable. - When you changed it to
state.arr = action.payload, you were overwriting the entire array with a single object each time, which is why only one item was stored.
内容的提问来源于stack exchange,提问作者Mohammed Bekele

