useState无法使用socket.io正确更新

时间:2020-05-02 23:54:49

标签: reactjs websocket socket.io react-hooks state

我正在通过socket.io提取数据,但是当侦听来自服务器的传入消息时,我的状态没有正确更新。

我可以看到数据是从套接字中正确提取的(对等50秒),但是setQuotes只是用服务器返回的新项替换了现有项(所以我的状态始终为1 )。

  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
    }); 
}

订阅//打开Web套接字流

3 个答案:

答案 0 :(得分:1)

您需要将侦听器移到订阅功能之外。 由于它是sideEffect,因此应将其包装在React.useEffect中 使用功能性setstate读取以前的值也是一个好主意。

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

答案 1 :(得分:0)

您可以在此处使用concat函数
setQuotes(prevState => prevState.concat(msg))

答案 2 :(得分:0)

在您的示例中,您像这样使用setState

setQuotes([...quotes, msg])

并且每次收到消息时,javascript引擎都会尝试在此函数范围内查找“ quotes”变量

function (msg) {

无法在此处找到它并移动到定义此功能的范围(组件功能的范围)。

对于每个函数调用,都有新的作用域。然后为每个渲染调用react组件函数。因此,在参数中带有“ msg”的函数(在其中使用setQuotes的情况下)每次都使用第一个渲染的“ quotes”状态。

在第一个渲染中,您有一个空数组。

然后您有[...firstEmptyArray, firstMessage]

然后您有[...firstEmptyArray, secondMessage]

然后您有[...firstEmptyArray, thirdMessage].

如果您将使用setQuotes like;

,可能可以修复它。
setQuotes(oldQuotes => [...oldQuotes, msg]);

通过这种方式,它将使用previousValue来计算新值。

PS。注意不要在每个渲染器中直接调用您的订阅函数,并使用正确的依赖项数组作为第二个参数将其置于useEffect中。