React使用PubNub实现聊天时多次调用函数setState未更新问题
问题根因
你代码中setNewChannels更新逻辑不生效的核心原因是直接引用了当前渲染闭包下的旧newChannels状态值,当该函数被多次并发调用时,所有调用拿到的newChannels都是函数触发瞬间的旧值,后续状态更新会直接覆盖前面的修改,最终仅最后一次更新生效。
修复方案
核心修改
将setNewChannels改为函数式更新写法,React状态更新函数传入回调时,回调的入参为当前最新的状态值,不受闭包旧值影响:
将原代码中
setNewChannels(newChannels.concat(newChannelMetadata))
替换为
setNewChannels(prev => prev.concat(newChannelMetadata))
完整优化后代码
增加双重存在性校验,避免因channelMetadata或newChannels的旧值导致重复添加频道:
const handleNewChannelCreation = async (newChannelId: string) => { const newChannelMetadata = (await pubnub.objects.getChannelMetadata({ channel: newChannelId })).data ?? dummyChannelMetadata setCurrentChannelMetadata(newChannelMetadata) if (channelMetadata) { const filteredChannels = channelMetadata.filter(isChannel) const isExistInChannelList = filteredChannels.findIndex((channel) => channel.id === newChannelMetadata.id) !== -1 if (!isExistInChannelList) { console.log("handleNewChannelCreation__", filteredChannels.length, "newChannel", newChannelMetadata.name) // 函数式更新保证拿到最新的newChannels值 setNewChannels(prevNewChannels => { // 额外校验是否已经添加到newChannels中,避免重复插入 const isExistInNewChannels = prevNewChannels.some(channel => channel.id === newChannelMetadata.id) return isExistInNewChannels ? prevNewChannels : prevNewChannels.concat(newChannelMetadata) }) } } setIsModalOpen(false) }
额外注意事项
- 如果
channelMetadata本身也是异步更新的状态,判断逻辑最好也下沉到setNewChannels的更新回调中,确保所有判断都基于最新状态 - 如果该函数可能在组件卸载后触发,建议增加取消请求或跳过状态更新的逻辑,避免控制台出现内存泄漏报错
内容的提问来源于stack exchange,提问作者hussian
相关产品推荐
相关产品推荐

