简体   繁体   中英

useEffect runs twice as much for each message sent

I am building a simple chat app with react, express and socket.io I got stuck on receiving message from backend server. Every time user receive some message, the useEffect will runs approximately twice as much as before so after 5 or 6 received messages the app start really slow down.

useEffect(() => {
    socket.on('mes', (data) => {
      setChat([...chat, data]);
    });
  }, [chat]);

any idea how to make it run just once every time user receive a message?

Whole code

import Chat from '../Chat/chat';
import queryString from 'query-string';
let socket;
const ChatRoom = ({ location }) => {
  const [name, setName] = useState('');
  const [room, setRoom] = useState('');

  const [message, setMessage] = useState('');
  const [chat, setChat] = useState([]);
  const ENDPOINT = 'http://localhost:4001/';

  useEffect(() => {
    const { name, room } = queryString.parse(location.search);
    setName(name);
    setRoom(room);

    socket = socketIOClient(ENDPOINT);
    socket.emit('join', { name, room });

    return () => {
      socket.emit('disconnect');
      socket.disconnect();
    };
  }, [ENDPOINT, location.search]);

  const click = (e) => {
    e.preventDefault();
    socket.emit('message', message);
    setMessage('');    
  };
  useEffect(() => {
    socket.on('mes', (data) => {
      setChat([...chat, data]);
    });
  }, [chat]);

  return (
    <div className="ChatRoom-Container">
      {chat.map((mes, index) => {
        return <Chat text={mes.text} user={mes.user} key={index}></Chat>;
      })}
      <input
        value={message}
        className="ChatRoom-Input"
        onChange={(e) => setMessage(e.target.value)}
        onKeyDown={(e) => {
          return e.key === 'Enter' ? click(e) : null;
        }}
      ></input>
    </div>
  );
};

export default ChatRoom;

Use setChat(prev => next) instead of setChat(value) so you don't have to reference the previous value from the closure:

useEffect(() => {
  socket.on('mes', (data) => {
    setChat(prev => [...prev, data]);
  });
}, []);
useEffect(() => {
    socket.on('mes', (data) => {
      setChat([...chat, data]);
    });
  }, [chat]);

Here in your dependency array you have the chat variable as a dependency. According to rules when the value of chat changes the effect runs. as a result after you call setChat() one time it changes the value of chat and as a result it runs the effect one more time. that's why your effect is being called twice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM