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.