Home > Mobile >  update object from reducer to useState
update object from reducer to useState

Time:10-07

I will try to update an object in reducer, once state is updated in reducer then i set the value using useState in functional component. But first time its working when i try to updated second time its not updated, showing only previous value. ReactNative

**Component**
const Catpoint = () => {
const { cPoint} = useSelector((state) => state.ckpoint)
const [ckpt, setCKPT] = useState(cPoint)

useEffect(()=>{
  setCKPT(cPoint)
},[cPoint])

const updatecPoint =  () => {
  ckpt.options =[{user:"suresh", status:"0"}, {user:"alex", status:"1" ]
  dispatch(updateCKPT(ckpt)
}
}

return <View>
   <TouchableOpacity onPress={()=> updatecPoint() }> Update User Status </TouchableOpacity>
</View>
export default Catpoint

**Reducer**

const initialcpoinState = {
cPoint:{
  pointName:"test",
  options:[{user:"suresh", status:"0"}, {user:"alex", status:"0" ]
}
}

const cpointSlice = createSlice({
    name: "cpointData",
    initialState: initialcpoinState,
    reducers: {
     updateCheckpointInfo:(state, action) => {
         
           Object.assign(state.cPoint, {...action.payload})

     }
})

export const {
    updateCheckpointInfo
} = cpointSlice.actions

export default cpointSlice


CodePudding user response:

This is a classic case of mutating state. The mutation occurs in this line:

ckpt.options = [{user:"suresh", status:"0"}, {user:"alex", status:"1"}]

You cannot mutate the ckpt object because it is a React state. In this case you're actually messing up your Redux state too. The initial value of the ckpt state comes from your useSelector hook so it is the same object instance in both places. Mutating one will change the other.


There is no need to have a local component state at all. Just dispatch the changes which you want to apply to the checkpoint and the cPoint variable from the useSelector hook will update automatically.

Your reducer is already merging the action.payload with the existing state.cPoint so you do not need to pass a complete checkpoint object in your action. You can simply pass the fields which you want to change.

const Catpoint = () => {
  const { cPoint } = useSelector((state) => state.ckpoint);

  const updatecPoint = () => {
    dispatch(
      updateCKPT({
        options: [{ user: "suresh", status: "0" }, { user: "alex", status: "1" }]
      })
    );
  };

  return (
    <View>
      <TouchableOpacity onPress={() => updatecPoint()}>
        Update User Status
      </TouchableOpacity>
    </View>
  );
};

export default Catpoint;
  • Related