A代码
if (current_knowledge.data.knowledge_base_results.length > 0 && !responseFlux.includes('paint')) {
knowledge_list = current_knowledge.data.knowledge_base_results;
let lastItem = chatHistoryRef.current.pop();
lastItem[2] = knowledge_list;
const content = [...chatHistoryRef.current, lastItem];
setChatHistory(content);
}
B代码
if (current_knowledge.data.knowledge_base_results.length > 0 && !responseFlux.includes('paint')) {
knowledge_list = current_knowledge.data.knowledge_base_results;
let lastItem = chatHistoryRef.current.pop();
lastItem[2] = knowledge_list;
chatHistoryRef.current.push(lastItem)
setChatHistory(chatHistoryRef.current);
}
我们看下上面的2块代码,B代码是有Bug,会造成页面不会渲染;
原因如下
第一种方法创建了 chatHistory 的新副本并使用 setChatHistory 更新状态,这种做法更符合React的不可变性原则。第二种方法直接修改了 chatHistoryRef.current 的内容,这可能导致不可预期的渲染行为,因为React可能没有检测到引用变化。第一种方法通常是更安全且推荐的做法,以避免隐含的bug和确保组件正确响应状态变化。
所以我们要记住,React的不可变性的原则;因为React内部会检测引用是否变化;
进阶
第一种写法可以用 use-immer 优化吗?
第一种写法可以用 use-immer 来优化。use-immer 提供了一种处理不可变数据的简便方法,允许你写出看似直接修改状态的代码,而实际上它会安全地产生新的不可变状态。这样可以让你的代码更简洁,同时保留React所推崇的不可变性原则。在你的场景中,use-immer 可以简化处理和更新 chatHistory 状态的逻辑。
if (current_knowledge.data.knowledge_base_results.length > 0 && !responseFlux.includes('paint')) {
knowledge_list = current_knowledge.data.knowledge_base_results;
let lastItem = chatHistoryRef.current.pop();
lastItem[2] = knowledge_list;
const content = [...chatHistoryRef.current, lastItem];
setChatHistory(content);
}
const [xx,setChatHistory] = useImmer([]);
if (current_knowledge.data.knowledge_base_results.length > 0 && !responseFlux.includes('paint')) {
const knowledge_list = current_knowledge.data.knowledge_base_results;
setChatHistory(draft => {
let lastItem = draft.pop();
lastItem[2] = knowledge_list;
draft.push(lastItem);
});
}