React中useEffect嵌套对象渲染时刷新页面报undefined错误
解决React异步加载嵌套对象时的初始渲染错误
你遇到的错误本质是异步数据加载完成前,组件已经开始渲染嵌套属性。初始渲染时,estoque(即store状态)还未被API返回的数据更新,此时它是undefined或空对象,直接访问estoque.param3.logradouro会因为param3不存在而抛出Cannot read properties of undefined错误。
下面是三种实用的解决方法:
方法1:给状态设置带嵌套结构的初始值
初始化store时,提前定义好嵌套对象的结构,确保初始渲染时param3是存在的空对象:
import { useState, useEffect } from 'react'; function EstoquePage() { // 初始化状态时定义完整的嵌套结构 const [store, setStore] = useState({ param1: '', param2: '', param3: { logradouro: '', bairro: '' } }); const [id] = useState('your-id-here'); useEffect(() => { async function fetchStore() { try { const storeResponse = await fetch(`http://localhost:8080/dbtable/${id}`); if(!storeResponse.ok){ throw new Error('Couldnt fetch any object.'); } const dataStore = await storeResponse.json(); setStore(dataStore); } catch (e) { console.error(e); } } fetchStore(); }, [id]); return ( <div> <p>{store.param1}</p> <p>{store.param2}</p> {/* 初始渲染时param3存在,不会报错 */} <p>{store.param3.logradouro}</p> <p>{store.param3.bairro}</p> </div> ); }
方法2:使用可选链操作符安全访问嵌套属性
ES2020引入的可选链操作符?.可以在属性不存在时返回undefined,而不是抛出错误,是处理这类场景最简洁的方式:
// 渲染时直接使用?. return ( <div> <p>{estoque.param1}</p> <p>{estoque.param2}</p> <p>{estoque?.param3?.logradouro}</p> <p>{estoque?.param3?.bairro}</p> </div> );
如果你的项目环境不支持ES2020,可以通过Babel插件或TypeScript启用该语法。
方法3:添加加载状态控制渲染时机
通过加载状态,在数据未准备好时显示加载提示,避免渲染未完成的数据:
import { useState, useEffect } from 'react'; function EstoquePage() { const [store, setStore] = useState(null); const [loading, setLoading] = useState(true); const [id] = useState('your-id-here'); useEffect(() => { async function fetchStore() { try { const storeResponse = await fetch(`http://localhost:8080/dbtable/${id}`); if(!storeResponse.ok){ throw new Error('Couldnt fetch any object.'); } const dataStore = await storeResponse.json(); setStore(dataStore); } catch (e) { console.error(e); } finally { // 无论请求成功或失败,都结束加载状态 setLoading(false); } } fetchStore(); }, [id]); // 加载中时显示提示 if (loading) { return <div>加载中,请稍候...</div>; } // 数据加载完成后再渲染 return ( <div> <p>{store.param1}</p> <p>{store.param2}</p> <p>{store.param3.logradouro}</p> <p>{store.param3.bairro}</p> </div> ); }
内容的提问来源于stack exchange,提问作者gustop01
相关产品推荐
相关产品推荐

