React v18.2.0中useEffect获数据后首次加载不渲染问题求助
React v18.2.0中useEffect首次加载数据不渲染,后续正常
我在React v18.2.0里用useEffect从API获取数据,首次加载页面时数据没渲染出来,但之后不管是点击页面其他选项还是切换表格行,只要触发重渲染,数据就能正常显示。
状态定义代码
let audioFileUrl = useSelector((state) => state.fetchAudioFileUrl); const [lang, setLang] = React.useState('English'); const isLoading = useSelector((state) => state.isLoadingDataView); const data = useSelector((state) => state.fetchIndividualItem.data); const [activeData, setActiveData] = React.useState(data.languages.english.data);
useEffect调用逻辑
useEffect(() => { dispatch(fetchdataspinnerstart()); if (audioAvailable) { dispatch(fetchAudioFileUrl(id, CLIENT_CONSTANTS.TYPE)); } else { audioFileUrl = '...'; } dispatch(fetchIndividualItem(id, CLIENT_CONSTANTS.TYPE)); }, []);
Redux Action代码
export const fetchIndividualItem = (docId, fetchType) => (dispatch) => { const id = docId; const type = fetchType; axios.get(`${baseuri}/sections/${id}?type=${type}`) .then((response) => { const { data } = response; dispatch(fetchindividualdatasuccess(data)); dispatch(fetchdataspinnersuccess); }) .catch((error) => { const errorMsg = error.message; dispatch(fetchdatafail(errorMsg)); }); };
问题根源
- 本地状态初始化依赖未就绪的Redux数据:组件首次渲染时,Redux里的
fetchIndividualItem.data还没拿到API返回结果,此时data.languages.english.data大概率是undefined,导致activeData初始值无效。而且Redux数据更新后,本地状态activeData不会自动同步,必须手动触发更新。 - Redux Action调用遗漏括号:
dispatch(fetchdataspinnersuccess)没加括号,导致没有正确触发loading状态的更新,不过这不是数据不渲染的核心原因。
解决方案
1. 监听Redux数据变化同步更新本地状态
移除activeData的初始值依赖,改用useEffect监听Redux中data的变化,当数据就绪后再更新本地状态:
const [activeData, setActiveData] = React.useState(null); // 监听Redux数据变化,同步更新activeData useEffect(() => { // 加可选链避免报错 if (data?.languages?.english?.data) { setActiveData(data.languages.english.data); } }, [data]); // 依赖Redux中的data,数据更新时触发
2. 直接使用Redux数据,取消本地状态
如果不需要对activeData做本地修改,完全可以直接使用Redux中的数据,省去维护本地状态的麻烦:
// 移除activeData本地状态,直接从Redux取数并加默认值 const activeData = data?.languages?.english?.data || [];
3. 修复Redux Action的调用错误
把dispatch(fetchdataspinnersuccess)改成dispatch(fetchdataspinnersuccess()),确保loading状态正确切换:
export const fetchIndividualItem = (docId, fetchType) => (dispatch) => { const id = docId; const type = fetchType; axios.get(`${baseuri}/sections/${id}?type=${type}`) .then((response) => { const { data } = response; dispatch(fetchindividualdatasuccess(data)); dispatch(fetchdataspinnersuccess()); // 加上括号调用action creator }) .catch((error) => { const errorMsg = error.message; dispatch(fetchdatafail(errorMsg)); }); };
4. 渲染时添加边界处理
在渲染组件前判断数据是否存在,避免因数据未就绪导致的报错:
// 示例渲染逻辑 if (!activeData) { return <div>加载中...</div>; } return ( // 你的组件内容 );
内容的提问来源于stack exchange,提问作者Shreehari
相关产品推荐
相关产品推荐

