aws-amplify-react的Connect组件先返回undefined数据的问题
解决AWS Amplify Connect组件初始渲染返回undefined导致应用崩溃的问题
我来帮你捋清楚这个问题的原因,再给你几个实用的解决方案~
为什么会出现两次undefined?
这其实是Connect组件的正常生命周期表现:
- 组件第一次挂载时,还没发起GraphQL查询,
data自然是undefined,所以getRoom也是undefined; - 紧接着组件内部会触发状态更新(比如检查本地缓存、发起网络请求),这时候请求还没完成,数据依然没就绪,所以第二次渲染还是返回
undefined; - 等GraphQL请求成功拿到数据后,第三次渲染才会返回正确的
getRoom数据。
有时候你会发现loading状态已经是false但getRoom还是undefined,这可能是因为缓存里没有对应数据,或者请求完成但返回的结果就是空(不过你的场景里后续能拿到正确数据,所以应该是前两种状态导致的)。
解决方案
方案1:利用loading状态+可选链操作符
这是最简洁的方式,既处理加载状态,又避免访问嵌套字段报错:
export const AppSyncTest = () => ( <Connect query={graphqlOperation(query)}> {({ data: { getRoom }, loading }) => { console.log(getRoom); // 加载中显示提示 if (loading) { return 'Loading room data...'; } // 使用可选链(?.),即使getRoom是undefined也不会崩溃 return ( <div className="App"> <header className="App-header"> <h1 className="App-title">Welcome to IntelliFM WebApp</h1> </header> <p className="App-intro"> Found room {getRoom?.id} with label {getRoom?.label} and description{' '} {getRoom?.description} </p> </div> ); }} </Connect> );
可选链是ES2020的语法,create-react-app默认支持,不需要额外配置。
方案2:解构时给getRoom设置默认值
如果不想用可选链,可以在解构data的时候给getRoom一个默认空对象,这样访问getRoom.id只会得到undefined,不会触发崩溃:
export const AppSyncTest = () => ( <Connect query={graphqlOperation(query)}> {({ data: { getRoom = {} }, loading }) => { console.log(getRoom); if (loading) { return 'Loading room data...'; } return ( <div className="App"> <header className="App-header"> <h1 className="App-title">Welcome to IntelliFM WebApp</h1> </header> <p className="App-intro"> Found room {getRoom.id} with label {getRoom.label} and description{' '} {getRoom.description} </p> </div> ); }} </Connect> );
方案3:保留你的空状态判断,同时结合loading
如果你想继续用原来的判断逻辑,可以加上loading的检查,让提示更清晰:
export const AppSyncTest = () => ( <Connect query={graphqlOperation(query)}> {({ data: { getRoom }, loading }) => { console.log(getRoom); if (loading) { return 'Loading...'; } if (!getRoom) { return 'Room data not found'; } return ( <div className="App"> <header className="App-header"> <h1 className="App-title">Welcome to IntelliFM WebApp</h1> </header> <p className="App-intro"> Found room {getRoom.id} with label {getRoom.label} and description{' '} {getRoom.description} </p> </div> ); }} </Connect> );
内容的提问来源于stack exchange,提问作者Pinguin Dirk
相关产品推荐
相关产品推荐

