React Native Expo中使用react-redux时多角色任务勾选状态同步异常问题求助
Hey there! No need to apologize for your English at all—let's work through this checkbox problem together.
The core issue here is immutable state violations in your Redux reducer, paired with shared memory references between your character objects. When you update one character's checkbox values, all others change because they’re actually pointing to the exact same underlying array in memory.
Why This Happens
Your current code uses Object.assign({}, state) to create a "new" state, but this only does a shallow copy. That means nested objects (like newState.LoaData.characters[id] and its inner value array) still reference the original state’s objects. If you created all characters from a shared template, their filteredContents[weekADay][firstIndex].value arrays are probably the same reference—so modifying one updates every character that shares it.
How to Fix It
You need to deep copy the nested parts of the state you’re modifying to break those shared references. Here are two reliable approaches:
1. Manual Deep Copy (No External Libraries)
Update your changeCheckbox function to clone all nested objects/arrays that you modify:
const changeCheckbox = (state, action) => { const { contentType, firstIndex, id, value } = action.payload; // Create a deep copy of the entire state (safe for plain data structures) const newState = JSON.parse(JSON.stringify(state)); if(contentType === 'daily') { const weekADay = newState.weekADay; const targetContent = newState.LoaData.characters[id].contents[contentType][weekADay][firstIndex]; // Replace the value array with a fresh copy of the incoming value targetContent.value = [...value]; } return newState; }
Note: JSON.parse(JSON.stringify()) works great for plain objects/arrays, but avoid it if your state includes functions, Dates, or other non-serializable values.
2. Use Immer (Recommended for Clean, Simple Code)
Immer lets you write "mutating" code that gets automatically converted into immutable updates. It’s ideal for nested Redux state:
First install Immer:
npm install immer
Then update your reducer:
import produce from 'immer'; const initialState = { LoaData: {}, weekADay: '', }; const reducer = (state = initialState, action) => { switch (action.type) { case 'CHECKBOX_REDUX': return produce(state, draft => { const { contentType, firstIndex, id, value } = action.payload; if(contentType === 'daily') { const weekADay = draft.weekADay; const targetContent = draft.LoaData.characters[id].contents[contentType][weekADay][firstIndex]; targetContent.value = [...value]; } }); default: return state; }; }
Immer handles all the deep copying under the hood, making your code cleaner and less error-prone.
Additional Check
Make sure when you create new characters, you’re not reusing the same value array template for every character. For example:
// ❌ Bad: Reuses the same array reference across all characters const defaultDailyValue = [false, false, false]; // ✅ Good: Creates a fresh array for each new character const getDefaultDailyValue = () => [false, false, false];
This ensures each character starts with their own independent set of checkbox values, so updates never cross over to other characters.
Give these fixes a try—they should resolve the issue where checking one character’s tasks updates all others!
内容的提问来源于stack exchange,提问作者Barami62

