React Native查询Firestore结果控制台正常但无法渲染到屏幕
React Native 调用 Firestore 获取用户名无法渲染问题
问题复现
在 React Native 应用中对接 Firestore 数据库实现用户名展示功能时遇到异常:
- 最初编写的获取用户名函数,在回调内通过
console.log打印username可以拿到正确结果,但无法将结果渲染到页面。
初始函数代码:function getUsername() { getDoc(doc(db, 'usernames', user!.uid)).then((userDoc) => { if(userDoc.exists()) { const username: string = userDoc.data()[user!.uid]; return username; } else { return 'error'; } }) }; - 直接在Text组件中调用该函数时,页面无任何文本展示,连
error提示都不显示:<Text>{getUsername()}</Text> - 怀疑是异步逻辑问题,尝试将函数改写为async形式后,应用直接崩溃,抛出错误:
Objects are not valid as a react child (found: object with keys {_u, _v, _w, _x}). If you meant to render a collection of children, use an array instead.
- 多次调整async写法后,出现两种情况:
- 写法1:无报错、无文本展示
function getUser() { getDoc(doc(db, 'usernames', user!.uid)).then(async(userDoc) => { if(userDoc.exists()) { await userDoc.data()[user!.uid]; } else { return 'error'; } }) }; - 写法2:直接触发上述React子元素非法错误
async function getUser() { await getDoc(doc(db, 'usernames', user!.uid)).then((userDoc) => { if(userDoc.exists()) { return userDoc.data()[user!.uid]; } else { return 'error'; } }) };
- 写法1:无报错、无文本展示
问题根因
- 初始的
getUsername函数本身没有返回值:getDoc是异步Promise操作,.then回调内的return只会作为Promise的 resolved 值,不会成为getUsername函数的对外返回值,因此Text组件拿到的是undefined,无法渲染内容。 - async函数默认返回Promise对象,React不支持直接将Promise作为子节点渲染,因此会抛出对象非法的错误。
- 对同步方法
userDoc.data()加await没有实际作用,且拿到值后没有触发视图更新,自然不会展示内容。
最终解决方案
通过useState钩子管理待渲染的用户名状态,待Firestore异步请求返回结果后更新状态,触发组件重渲染即可正常展示,可用代码如下:
const[displayUsername, setDisplayUsername] = useState<string>(''); function getUser() { getDoc(doc(db, 'usernames', user!.uid)).then((userDoc) => { if(userDoc.exists()) { setDisplayUsername(userDoc.data()![user!.uid]); } else { setDisplayUsername('error'); } }) };
需要在组件挂载阶段(如useEffect钩子内)调用getUser()触发数据拉取,渲染时直接绑定状态值即可:
<Text>{displayUsername}</Text>
内容的提问来源于stack exchange,提问作者Cam
相关产品推荐
相关产品推荐

