Josh Susa
Josh Susa

Reputation: 415

ReactJS render function isn't being updated

I'm attempting to make a chat function using material UI. I created a function where users can post new chat messages which are then sent through the reducer and then saved in the redux store. This process works as intended except for the fact that the new chat message only appears after the user refreshes the page. I'm wondering why my render function isn't being updated. Here's the main chat display.

const ChatFunction = (props) => {
  const classes = useStyles();
  const { user } = props;
  const userMessages = props.userMessages || {};
};

const mapStateToProps = (state) => {
  return {
    user: state.user,
    userMessages:
      state.messages &&
      state.messages.find(
        (userMessages) => userMessages.otherUser.username === state.currentMessage
      )
  };
};

export default connect(mapStateToProps, null)(ChatFunction);

The postMessage function is then passed through my reducer and my reducer function is called to add the new message to the messages array.

export const newMessage = (state, payload) => {
  const { message, sender } = payload;
  return state.map((userMess) => {
    if (userMess.id === message.Id) {
      userMess.messages.push(message);
      userMess.latestMessageText = message.text;
      return userMess;
    } else {
      return userMess;
    }
  });
};

So, does anyone know why this isn't refreshing properly?

Upvotes: 1

Views: 73

Answers (1)

Drew Reese
Drew Reese

Reputation: 203466

You are mutating the user's messages array when you directly push into it and mutate other properties.

export const newMessage = (state, payload) => {
  const { message, sender } = payload;
  return state.map((userMess) => {
    if (userMess.id === message.Id) {
      userMess.messages.push(message); // <-- mutation!!
      userMess.latestMessageText = message.text; // <-- mutation!!
      return userMess;
    } else {
      return userMess;
    }
  });
};

When updating state in react you need to shallow copy state and any nested state being updated into new object references to React's reconciliation works.

export const newMessage = (state, payload) => {
  const { message, sender } = payload;

  return state.map((userMess) => { // <-- shallow copy of state
    if (userMess.id === message.Id) {
      return { // <-- return new user message object
        ...userMess, // <-- shallow copy of previous user message object
        messages: [message.text, ...userMess.messages], // prepend message, return new array
        latestMessageText: message.text, // update property
      };
    } else {
      return userMess;
    }
  });
};

Upvotes: 1

Related Questions