useState не обновляется правильно с помощью socket.io - PullRequest
0 голосов
/ 03 мая 2020

Я получаю данные через socket.io, но при прослушивании входящих сообщений с сервера мое состояние не обновляется правильно.

Я вижу, что данные правильно извлекаются из сокета (50 запросов в секунду), но setQuotes просто заменяет существующий элемент новым элементом, возвращаемым с сервера (поэтому мое состояние всегда имеет длину one).

  const [quotes, setQuotes] = useState([])
 const subscribe = () => {
    let getQuote = 'quote.subscribe';
    socket.emit(getQuote, {});
    socket.on('listenAction', function (msg) {
        setQuotes([...quotes, msg]) // This just replace the entire state instead of adding items to the existing array
    }); 
}

Подписаться // Открыть поток веб-сокетов

Ответы [ 3 ]

1 голос
/ 03 мая 2020

Вам необходимо переместить слушателя за пределы функции подписки. Поскольку это побочный эффект, вы должны заключить его в React.useEffect Также неплохо использовать функциональное состояние для чтения предыдущих значений.

React.useEffect(() => {
    socket.on('listenAction', function (msg) {
        setQuotes((quotes) => [...quotes, msg])
    }); 
}, []);

0 голосов
/ 03 мая 2020

В вашем примере вы используете setState следующим образом

setQuotes([...quotes, msg])

И каждый раз, когда вы получаете сообщение, javascript движок пытается найти переменную "quotes" в области действия этой функции

function (msg) {

Он не может найти его здесь и перейти к области действия, где была определена эта функция (область действия компонента).

Для каждого вызова функции существует новая область действия. И реагировать на вызовы компонент функции для каждого рендера. Итак, ваша функция с «msg» в аргументах, где вы используете setQuotes, каждый раз использует состояние «quotes» с первого рендера.

В первом рендере у вас есть пустой массив.

Затем вы есть [...firstEmptyArray, firstMessage]

Тогда у вас есть [...firstEmptyArray, secondMessage]

Тогда у вас есть [...firstEmptyArray, thirdMessage].

Возможно, вы можете это исправить, если будете использовать setQuotes, как;

setQuotes(oldQuotes => [...oldQuotes, msg]);

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

PS. Помните, что не следует вызывать функцию подписки непосредственно в каждом рендере и использовать ее в качестве эффекта-эффекта с правильным массивом зависимостей в качестве второго аргумента.

0 голосов
/ 03 мая 2020

Вы можете использовать Concat Fun c здесь
setQuotes(prevState => prevState.concat(msg))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...