我正在通过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套接字流
答案 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中。