页面刷新时React useEffect无法填充状态,致words.map报错
问题分析
页面刷新时触发words.map is not a function错误,核心原因是API返回的数据不是数组,导致setWords(data)把初始为空数组的words改成了非数组类型(比如错误对象、null或嵌套数组的对象)。
至于注释useEffect再恢复就正常的情况,大概率是刷新时token还未初始化完成,请求用了空token导致鉴权失败,API返回了错误内容;而后续手动恢复useEffect时,token已经就绪,请求成功返回了数组。
解决方案
1. 先排查API返回值
在case2的const data = await response.json();后面加控制台打印,刷新页面看真实返回:
const data = await response.json(); console.log('Case2返回数据:', data);
- 如果返回的是嵌套数组的对象(比如
{vocabList: [...]}),要改成setWords(data.vocabList)而非直接setWords(data); - 如果返回错误对象(比如
{error: "Unauthorized"}),说明token在刷新时未就绪,请求未通过鉴权。
2. 给words加类型兜底
不管API返回什么,强制保证words始终是数组:
// case1和case2中统一修改 const data = await response.json(); setWords(Array.isArray(data) ? data : []);
3. 补全useEffect的依赖项
你的useEffect里用到了token和id,但依赖项只有wordText,这会导致:
- 刷新时
token未初始化就发起请求,返回错误; id变化时不会重新触发请求。
补全依赖项:
useEffect(() => { // ... 原有请求逻辑 }, [wordText, token, id])
4. 渲染时加安全校验
在map之前先判断words是否为数组,避免报错,同时修正JSX的写法(不要用数组包裹元素,必须加唯一key):
return ( <div> {Array.isArray(words) && words.map((word, index) => ( <div key={word.id || index}> <h1 onClick={(e) => { setWordText(word.word_text); handleClick(index); translateWord(e) }}> {word.word_text} </h1> </div> ))} </div> )
注:优先用
word.id作为key,index是兜底方案,避免React渲染警告。
5. 处理token加载状态
如果token是异步获取的(比如从localStorage读取),要确保token存在再发起请求:
const getWordsBlock = async () => { if (!token) return; // token未就绪时不发起请求 // ... 原有请求代码 }
内容的提问来源于stack exchange,提问作者M.good
相关产品推荐
相关产品推荐

