react 初学遇到的问题
1. useEffect依赖项变化时并没有执行
源码
useEffect(() => {
const selectedComp = selects.find(select => select.value === selected);
selectedComp && setSelectedComp(selectedComp);
}, [selected, selects, selectedComp]);
分析
-
从提供的代码片段来看,这一行代码本身的逻辑是在查找
selects
数组中value
属性等于selected
的元素,并将这个元素赋值给状态selectedComp
-
这段代码可能出现问题的原因主要可能包括以下几点:
1. 查找结果为 undefined
:
-
如果
selects
数组中没有任何一个元素的value
属性与selected
相等,find
方法将返回undefined
。这可能不是你的预期行为,尤其是如果你后续的代码依赖于selectedComp
总是一个有效对象的话。确保你的代码能够妥善处理这种情况:const selectedComp = selects.find(select => select.value === selected); if (selectedComp) { setSelectedComp(selectedComp); } else { // 处理未找到匹配项的情况,例如设置一个默认值或更新状态以反映未找到 }
2. 状态更新异步性
-
setSelectedComp
是一个异步操作,这意味着状态的更新不会立即反映。如果你在调用setSelectedComp
之后立即依赖于selectedComp
的新值,可能会遇到问题。React 状态更新可能会被批处理,且实际更新的时机由 React 控制。正确的做法是在另一个useEffect
中,依赖于selectedComp
来执行需要该状态更新后的操作:useEffect(() => { //依赖于 selectedComp 的逻辑 }, [selectedComp]);
3. 检查是否有错误导致中断
-
如果
useEffect
中的代码抛出了错误,可能会导致后续代码不执行。尽管代码应该在错误之前执行,但值得确认是否有其他代码抛出了错误,特别是如果selectedComp
是undefined
(即没有找到配的 select ),这可能会导致问题。你可以添加trycatch
块来捕获并查看是否有错误发生:useEffect(() => { try { const selectedComp = selects.find(select => select.value === selected); if (!selectedComp) { console.error("未找到匹配的 select"); return; } setSelectedComp(selectedComp); } catch(error) { console.error("useEffect 错误:",error); } }, [selected, selects])
2. 函数获取不到最新的状态值
源码
// 获取答案
const handleGetAnswer = (item: AnswerFields) => {
const { question, content, faqs } = item;
// 答案写入 todo...
setInputValue(question);
handleSendText();
};
// 发送信息 且机器人回复处理
const handleSendText = async () => {
if (!inputValue) return;
// ...
};
分析
- 此时
handleSendText
函数调用时,期望获得最新的inputValue
状态值,但此时遇到问题:在handleSendText
里获取不到最新的inputValue
值,这是因为状态更新时异步的,而且在set
之后立即调用的函数内使用的是旧值
解决方案
- 在
useEffect
中调用handleSendText
方法
实现方式
-
需要增设状态值
shouldSendText
来标记是否需要发送文本 -
用户回车且
inputValue
有效时,setShouldSendText(true)
-
使用
useEffect
监听shouldSendText
,若为true
则调用handleSendText
且设置setShouleSendText(false)
// 获取答案
const handleGetAnswer = (item: AnswerFields) => {
const { question, content, faqs } = item;
// 答案写入 todo...
setInputValue(question);
setShouldSendText(true);
};
// 用户回车发送消息
const handleKeyDown = event => {
if (event.key === 'Enter') {
setShouldSendText(true);
}
};
// 发送信息 且机器人回复处理
const handleSendText = async () => {
setShouldSendText(false);
if (!inputValue) return;
// ...
};
useEffect(() => {
shouldSendText && handleSendText();
}, [shouldSendText]);