React useState не обновляется, в сокете.события ввода-вывода

#reactjs #socket.io #webrtc

#reactjs #socket.io #webrtc

Вопрос:

Я пытаюсь обновить свое состояние в сокете.событие ввода-вывода, но отражаются только самые последние изменения, а предыдущие изменения исчезли

   const [connStatus, setStatus] = useState({});
  const newConn = (user_id) => {
    console.log("previous ", connStatus);
    console.log("new status ", { ...connStatus, [user_id]: true });
    setStatus({ ...connStatus, [user_id]: true });
  };
  

я использую эту функцию newConn для обновления значений,

     props.socket.on("ANSWER", (incoming) => {
     
      const desc = new RTCSessionDescription(incoming.sdp);

      peers.current[incoming.caller]
        .setRemoteDescription(desc)
        .then((data) => {
          // set conn as true
          console.log(connStatus, { ...connStatus, [incoming.caller]: true });
          newConn(incoming.caller);
        })
        .catch((e) => console.log(e));
    });
  

Предыдущее состояние всегда регистрируется как пустое {} , т.Е. Его начальное значение, а новое состояние обновляется, но отбрасывает все предыдущие значения.

Для

 newConn("key1"); newConn("key2");
  

журналы выглядят так

 previous {}
new status {"key1" : true}

previous {}
new status {"key2" : true}
  

используя сигнатуру функции, например

   const newConn = (user_id) => {
    setStatus((prevState) => {
      console.log("previous ", prevState);
      console.log("new status ", { ...prevState, [user_id]: true });
      return { ...connStatus, [user_id]: true };
    });
  };
  

Для

 newConn("key1"); newConn("key2"); newConn("key3");
  

журналы выглядят так

 previous {}
new status {"key1" : true}

previous {"key1" : true}
new status {"key1" : true,"key2" : true}

previous {"key2" : true}
new status {"key2" : true,"key3" : true}
  

Обновить

Я нашел решение, но не уверен, почему оно работает, а мои предыдущие попытки нет

   const newConn = (user_id) => {
    setStatus((prevState) => {
      console.log("previous ", prevState);
      console.log("new status ", { ...prevState, [user_id]: true });
      const newState = { ...prevState, [user_id]: true };

      return newState;
    });
  };
  

Использование newConn дает мне требуемый результат.

Комментарии:

1. Можете ли вы опубликовать структуру connStatus?

2. @Mark я обновил сообщение, надеюсь, это поможет, connStatus — это просто объект со { [string] : bool } структурой

Ответ №1:

Используйте сигнатуру функции setStatus :

 const [connStatus, setStatus] = useState({});
const newConn = (user_id) => {
    console.log("previous ", connStatus);
    console.log("new status ", { ...connStatus, [user_id]: true });
    setStatus(s => ({ ...s.connStatus, [user_id]: true }));
           // ^ HERE
  };
  

Комментарии:

1. я думаю, вы имеете в виду, setStatus(s => ({ ...connStatus, [user_id]: true })); что причина s.connStatus равна нулю, но даже сигнатура функции не работает.

2. @sasta_achar, весь смысл функции заключается в использовании previousState , отмеченном как s здесь , и вычислении следующего состояния. так ...s.connState на самом деле правильно. Также { ...null, 1: 1 } приводит к {1:1} . Итак, то, что у меня есть, правильно. Удачи.

3. Но если вы хотите просто заменить свое состояние как newState, не используя какое-либо предыдущее состояние, которое вы можете просто использовать return newState , зачем использовать лишнее {...s.key, newState} , также я думаю, что использование prevState (здесь s), когда не требуется, может вызвать проблемы в будущем, например, если бы мое состояние было таким state : { connStatus : "some value" } , тогда ваш ответ имел бывызвало нежелательные результаты, но, поскольку в моем случае оно равно нулю, оно работало нормально