Реагируйте на состояние, не объединяя старое состояние в новое. - PullRequest
1 голос
/ 24 марта 2020

согласно многим примерам это должно работать:

const [_timeseries, $timeseries] = useState({hi:'lol'})

useEffect(() => {

socket.on('plot', e => {
 let keyname = Object.keys(e)[0]
 $timeseries({..._timeseries, [keyname] : value)})
}

}, [])

console.log(_timeseries) // here results in the initial state, not the set state

При первом слиянии работает. Но как только появляется новое событие с другим именем ключа, оно снова заменяет все. Вместо добавления нового ключа с [keyname], старый [keyname] заменяется.

Ответы [ 2 ]

1 голос
/ 24 марта 2020

Проблема в том, что закрывает .

Обратный вызов, назначенный для useEffect, закрывает начальное значение _timeseries в своей лексической области и никогда не обновляется.

Чтобы исправить это, вам нужно использовать функционал useState, который использует самое последнее состояние в своем обратном вызове:

const [_timeseries, $timeseries] = useState({hi:'lol'})

useEffect(() => {
socket.on('plot', e => {
 let keyname = Object.keys(e)[0]
 $timeseries(timeSeries => {...timeseries, [keyname] : value)})
}

}, [])
1 голос
/ 24 марта 2020

Хук useState предоставляет вам функцию, которая полностью заменяет состояние новым значением (не объединяет его): https://reactjs.org/docs/hooks-state.html

However, unlike this.setState in a class, updating a state variable always replaces it instead of merging it.

Вы можете использовать setState с функцию и объедините ее самостоятельно:

$timeseries((old) => ({...old, [keyname] : value)}))

Если вы используете ее без функции, она может иметь старые значения (потому что вы не указываете ее как зависимость от useEffect)

...