Search code examples
reactjsreact-hooksfrontendreact-forms

Reactjs form is not reflecting changes on submission


This is my code

  const [messages, setMessages] = useState(messagesList);

  const [addMessage, setAddMessage] = useState({
    messageSent: '',
  });

  const addMessageChange = (event) => {
    event.preventDefault();
    const fieldName = event.target.getAttribute("name");
    const fieldValue = event.target.value;
    const addMessageData = { ...addMessage };
    addMessageData[fieldName] = fieldValue;
    setAddMessage(addMessageData);
  };

  const addMessageSubmit = (event) => {
    event.preventDefault();
    const newMessage = {
      id: 18,
      sender: "Aakanksha Mantri",
      textMessage: addMessage.messageSent,
      sentbyUser: true,
      time: "00:45",
    };

    const newMessages = [...messages, newMessage];
    setMessages(newMessages);
  };
<div className="chat-body">
        {messagesList.map((messageData) => (
          <div className={messageData.sentbyUser ? 'message-received' : 'message-sent'}>
            <p className="message-name">{messageData.sender}</p>
            {messageData.text} <span className="message-time">{messageData.time}</span>
          </div>
        ))}
      </div>
<form onSubmit={addMessageSubmit}>
  <div className="message-input">
    <input type="text" placeholder="Type a message" name="messageSent" onChange={addMessageChange}></input>
    <button type="submit">Send!</button>
  </div>
</form>

Upon submitting, I would want the message entered to be added in the json file that contains the dummy data and has been imported. Also, the chat-body div should reflect the changes made on form submission.


Solution

  • The issue is that you are updating local messages state but rendering the imported static JSON data.

    const [messages, setMessages] = useState(messagesList);
    
    ...
    
    <div className="chat-body">
      {messagesList.map((messageData) => (
        <div className={messageData.sentbyUser ? 'message-received' : 'message-sent'}>
          <p className="message-name">{messageData.sender}</p>
          {messageData.text} <span className="message-time">{messageData.time}</span>
        </div>
      ))}
    </div>
    

    The component should be mapping the messages state. Don't forget a valid React key on the mapped elements.

    <div className="chat-body">
      {messages.map((messageData) => (
        <div
          key={messageData.id} // <-- or any unique property
          className={messageData.sentbyUser
            ? 'message-received'
            : 'message-sent'
          }
        >
          <p className="message-name">{messageData.sender}</p>
          {messageData.text} <span className="message-time">{messageData.time}</span>
        </div>
      ))}
    </div>
    

    Aside

    I strongly suggest using functional state updates whenever a component is updating state from a previous state.

    const addMessageChange = (event) => {
      event.preventDefault();
    
      const { name, value } = event.target;
    
      setAddMessage(message => ({
        ...message,
        [name]: value
      }));
    };
    
    const addMessageSubmit = (event) => {
      event.preventDefault();
    
      const newMessage = {
        id: 18,
        sender: "Aakanksha Mantri",
        textMessage: addMessage.messageSent,
        sentbyUser: true,
        time: "00:45",
      };
    
      setMessages(messages => [...messages, newMessage]);
    };