React Native调用WordPress API出现evaluating 'source'未定义错误如何解决
问题原因
首先需要明确:你觉得async/await没有生效是正常的React渲染逻辑,useEffect的回调函数会在组件首次渲染完成后才异步执行,因此组件第一次渲染时会先走return中的渲染逻辑,你已经加了loaded状态判断,首次渲染只会展示加载动画,不会访问业务数据,崩溃的核心原因是以下两点:
- 接口返回数据的嵌套字段可能缺失,你直接访问深层属性(比如
response.data.content.rendered、postData.title.rendered)时,若上层属性为undefined就会抛出异常 - 你混合使用
async/await和then/catch的写法,虽然语法上没有错误,但请求成功后处理数据的代码如果抛出异常,容易出现状态更新不完整的问题 useEffect依赖数组为空,若路由参数postId发生变化,不会重新请求数据,可能出现旧数据访问异常的问题
解决方案
按以下步骤修改代码即可解决崩溃问题:
- 所有访问嵌套对象属性的位置加上可选链操作符
?.,同时给必填字段添加兜底值 - 将请求逻辑替换为
try/catch写法,统一处理异常,出错时也更新loaded状态避免一直加载 - 给
useEffect添加postId依赖,保证参数变化时重新拉取对应文章数据
修改后完整代码
import React, { useState, useEffect } from "react"; import { ActivityIndicator, Text, View, ScrollView, Image, useWindowDimensions, } from "react-native"; import HTMLView from "react-native-htmlview"; import globalStyles from "../constant/globalStyle"; import axios from "axios"; import moment from "moment"; import { Colors } from "../constant/colors"; const PostDetail = ({ route }) => { const { postId } = route.params; const [postData, setPostData] = useState({}); const [loaded, setLoaded] = useState(false); const [source, setSource] = useState(""); useEffect(() => { // postId不存在直接终止请求 if (!postId) return; const fetchData = async () => { try { const response = await axios.get( `https://bachrasouthpanchayat.in/wp-json/wp/v2/posts/${postId}?embed=true` ); const data = response.data || {}; setPostData(data); // 给source加兜底空字符串,避免content不存在时报错 setSource(data?.content?.rendered || ""); setLoaded(true); } catch (error) { console.log(error, error.message); // 出错也更新加载状态,避免一直停留在加载页 setLoaded(true); } }; fetchData(); }, [postId]); // 加上postId依赖,参数变化自动重新请求 const { width } = useWindowDimensions(); return ( <ScrollView style={{ ...globalStyles.container, backgroundColor: Colors.BACKGROUND_SCREEN, }} > {loaded ? ( <> {/* 判断特色图存在才渲染Image组件,避免uri为undefined时报错 */} {postData?.jetpack_featured_media_url && ( <Image style={{ width: "100%", height: 250, }} source={{ uri: postData.jetpack_featured_media_url }} resizeMode="cover" /> )} <Text style={globalStyles.primaryHeading}> {/* 标题加兜底文本 */} {postData?.title?.rendered || "暂无标题"} </Text> <View style={{ paddingHorizontal: 18 }}> <View style={{ flexDirection: "row", justifyContent: "space-between", alignItems: "center", marginBottom: 10, }} > <Text style={{ ...globalStyles.date, fontSize: 20, fontWeight: "700", }} > {/* 日期加兜底 */} {postData.date ? moment(postData.date).format("LL") : "暂无日期"} </Text> </View> <HTMLView stylesheet={{ p: { fontSize: 20, color: "white", textAlign: "justify" }, h1: { color: "white", fontSize: 32, }, h2: { color: "white", fontSize: 28, }, figure: { backgroundColor: "red", width: "100% !important", height: "100% !important", }, img: { width: "100% !important", backgroundColor: "green", }, }} value={source} imagesMaxWidth={width} /> </View> </> ) : ( <View style={{ alignItems: "center", justifyContent: "center", height: 300, // 给加载容器加固定高度,避免加载动画在顶部 }} > <ActivityIndicator size={60} color={Colors.PRIMARY_GREEN} /> </View> )} </ScrollView> ); }; export default PostDetail;
内容的提问来源于stack exchange,提问作者Shoubhik Raj
相关产品推荐
相关产品推荐

