React StrictMode下useEffect重复执行及清理函数实现咨询
解决React StrictMode下useEffect重复执行导致的重复调用问题
问题根源
你的代码核心问题有两个:
Chat组件的useEffect依赖数组为空,既无法响应新的用户消息,又会在StrictMode开发环境下被强制执行两次;- 状态更新和服务调用没有做幂等处理,导致重复执行时重复添加消息、调用服务。
解决方案
1. 修正useEffect依赖并添加幂等控制
通过useRef记录已处理过的用户消息,即使StrictMode触发两次useEffect,也能跳过重复执行的逻辑;同时补全依赖数组,确保新消息能触发处理。
修改后的Chat组件代码:
const Chat = (props) => { const { messages, lastUserMessage, setChatBotMessages, callService } = props; // 用ref记录已处理的消息,避免重复执行 const processedMsgRef = useRef(null); useEffect(() => { if (lastUserMessage && lastUserMessage.trim() && lastUserMessage !== processedMsgRef.current) { // 标记当前消息为已处理 processedMsgRef.current = lastUserMessage; // 完整更新状态,保留原有字段 setChatBotMessages((prev) => ({ ...prev, messages: [...prev.messages, lastUserMessage] })); // 调用服务 callService(lastUserMessage); } }, [lastUserMessage, setChatBotMessages, callService]); // 补全所有依赖 return <div>{messages.map((msg, idx) => <span key={idx}>{msg} </span>)}</div>; };
2. 完善服务调用后的状态处理
在callService中更新状态时,建议清空lastUserMessage,从根源上避免同一消息被重复触发处理:
const callService = (lastUserMessage) => { // 模拟异步服务调用(实际项目中替换为真实请求) setChatBotMessages((prev) => ({ ...prev, messages: [...prev.messages, "New response from service"], lastUserMessage: "" // 清空用户消息,防止重复处理 })); };
3. 优化初始状态传递
ChatBot组件的初始状态可以直接解构chatBotConfig,避免冗余代码:
const [chatBotMessages, setChatBotMessages] = useState({ ...chatBotConfig });
关键说明
- 依赖数组必须完整:useEffect的依赖要包含所有用到的外部变量,否则会出现闭包过期问题,且无法响应新的用户输入;
- useRef做幂等标记:useRef的内容不会随组件渲染重置,适合记录状态类的标记,用来过滤重复执行的逻辑;
- 状态更新需保留完整结构:更新状态时使用
...prev保留未修改的字段,避免丢失lastUserMessage等状态数据。
内容的提问来源于stack exchange,提问作者Krishnath
相关产品推荐
相关产品推荐

