React useState Hook字符串值显示不一致问题排查与解决
React状态更新异步导致的词典查询显示问题
问题场景
我在Github上准备了一个简单的测试项目来演示问题,动画截图展示了异常现象:当在MUI输入框中反复输入或删除"A"时,词典对象中的单词释义显示不一致,需要多次尝试才能正确显示"AA"对应的"Rough, cindery lava"。
页面包含一个MUI TextField、点赞/点踩图标和显示单词释义的文本,核心代码如下:
const DICT = { AA: "Rough, cindery lava", AB: "An abdominal muscle", ABS: "Abdominal muscles", ABSQUATULATE: "", ABSQUATULATING: "", ABY: "Pay the penalty", }; export default function App() { const [word, setWord] = useState(""); const [description, setDescription] = useState(""); const [found, setFound] = useState(false); const handleChange = (ev) => { ev.preventDefault(); const key = ev.target.value.trim().toUpperCase(); setWord(key); if (key.length < 2) { setDescription(""); return; } setFound(DICT.hasOwnProperty(key)); if (!found) { setDescription("The word is not found in the dictionary"); return; } setDescription(DICT[key] || ""); }; return ( <Box component="form" noValidate autoComplete="on"> <TextField id="wordInput" label="Enter a word" value={word} onChange={handleChange} /> <Box> {found ? <ThumbUp color="primary" /> : <ThumbDown color="error" />} </Box> <Box>{description}</Box> </Box> ); }
作为React新手,我推测应该使用钩子的prevState形式,但不清楚针对三个状态中的哪一个以及如何使用,对此感到困惑。
修复方案(无需useEffect)
在理解问题根源后,我在未使用useEffect钩子的情况下实现了修复,核心是直接使用输入的key而非异步更新的word状态值,代码如下:
export default function App() { const [word, setWord] = useState(""); const [description, setDescription] = useState(""); const [found, setFound] = useState(false); const handleChange = (ev) => { ev.preventDefault(); const key = ev.target.value.trim().toUpperCase(); setWord(key); // 下面使用key而非word,因为后者是异步更新的 if (key.length < 2) { setFound(false); setDescription(""); } else { setFound(Object.prototype.hasOwnProperty.call(DICT, key)); setDescription(DICT[key] || "The word is not found in the dictionary"); } }; return ( <Box component="form" noValidate autoComplete="on"> <TextField id="wordInput" label="Enter a word" value={word} onChange={handleChange} /> <Box> {found ? <ThumbUp color="primary" /> : <ThumbDown color="error" />} </Box> <Box>{description}</Box> </Box> ); }
内容的提问来源于stack exchange,提问作者Alexander Farber
相关产品推荐
相关产品推荐

