React中setTimeout读取旧state导致新增bot消息时用户消息丢失如何修复
问题修复方案
你遇到的是React函数组件经典的闭包陷阱问题:setTimeout的回调函数捕获了调用addBotMessage那一刻的messages旧值,2秒后执行的时候基于旧值拼接新消息,自然就覆盖了之前addUserMessage新增的用户消息。
修复方法:使用useState的函数式更新语法
useState返回的更新函数支持传入一个回调,回调的第一个参数就是最新的state值,不受闭包捕获的旧值影响,修改代码如下:
const [messages, addMessages]=useState([]); const addBotMessage=async (value, callback)=>{ addUserMessage(value, callback); setTimeout(()=>{ // 改用函数式更新,拿到最新的messages addMessages(prevMessages => [...prevMessages,{content:BotContent[callback], time:getTime(), author:'bot'}]); },2000) } const addUserMessage=(value, callback)=>{ if(!value) return; // 这里也建议同步改成函数式更新,避免其他场景下出现同样的闭包问题 addMessages(prevMessages => [...prevMessages,{content:value, time:getTime(), author:'user'}]); }
原理解释
- 直接传值给
addMessages的时候,使用的是当前作用域里捕获的messages旧值 - 传回调给
addMessages的时候,React会自动把最新的state作为参数传给回调,不管回调什么时候执行,拿到的都是当前最新的消息列表,不会出现旧值覆盖新值的问题
内容的提问来源于stack exchange,提问作者Mr.Kurosava
相关产品推荐
相关产品推荐

