Home > Enterprise >  Adding an element to a react reducer state array, Is doubling the element every append
Adding an element to a react reducer state array, Is doubling the element every append

Time:06-28

store.js


const initialState = {
    messagelist: []
}

const reducerAllMessages = (state=initialState, action) => {
    if(action.type === "newMessage") {
        console.log("state", state);
        return {...state, messagelist:[...state.messagelist, action.payload]}
    }
        return state;
}

const store = createStore(reducerAllMessages)

export default store

messagelist.js

  const [data, setData] = useState([]);
  const messages = useSelector((state) => state.messagelist)
  const dispatch = useDispatch()
 

  useEffect(() => {
    socket.on("user-to-admin", (payload) => {
        console.log("socket payload", payload);
        // setData([...data,{ who: "him", message: payload.message} ]);
        dispatch({type:"newMessage",payload:payload})

      },
      [messages]
    );
  });

  let list = () => {
    if (data === undefined ) {
    } else {
      return messages.map((e) => <ChatBubble who={e.who} message={e.message} />);
    }
  };
  return <ul>{list()}</ul>;
}

IMAGE

https://i.stack.imgur.com/mui6M.png

Don't know why it is causing to multiply the elements in the array every time i am pushing elements

CodePudding user response:

Your socket event handler is wrapped in useEffect, which does not have any dependencies. When you dispatch 'newMessage' event, and it is processed by store and updates to message state slice are pushed, your component gets re-rendered. Re-rendering causes a new socket event handler to be attached, thus doubling your messages after every event. Changing your code to below snippet should fix this:

useEffect(() => {
  socket.on("user-to-admin", (payload) => {
      console.log("socket payload", payload);
      // setData([...data,{ who: "him", message: payload.message} ]);
      dispatch({type:"newMessage",payload:payload})

    },
    [messages]
  );
}, []);

Now useEffect would only run when component is rendered the first time.

  • Related