1

我是 React Native 的新手。我正在制作一个从 API 获取数据并将其显示在屏幕上的应用程序。渲染此屏幕时出现以下错误:渲染错误 undefined is not an object (evalating 'character.origin.name')

这里的代码在屏幕上:

const CharacterDetailScreen = (props) => {

    const { styles, colors } = useThemedValues(getStyles);
    const loc = useLocalization();

    **// state for character detail**
    const [character, setCharacter] = useState([])

    **// this id come from previous screen**
    const { characterId } = props.route.params

    useEffect(()=>{
        Axios.get('character/'+characterId)
            .then(response =>{
                characterDetail = response.data
                setCharacter(characterDetail)
                console.log(characterDetail.name) // if characterId=89, writes "dale" in console
            })
            .catch(error => {
                console.log(error)
            })
    },[])
 
    return (
        <View style={styles.container}>
            <View style={styles.imageContainer}>
                <Image source={{ uri: character.image }}
                    style={styles.image}
                />
            </View>
            <View style={styles.characterNameContainer}>
                <Text style={styles.characterName}>{character.name}</Text>
            </View>
            <View style={styles.detailContainer}>
                <Text style={styles.detailText} >{loc.t(texts.status)}{character.status}</Text>
                <Text style={styles.detailText} >{loc.t(texts.species)}{character.species}</Text>
                <Text style={styles.detailText} >{loc.t(texts.gender)}{character.gender}</Text>
                <Text style={styles.detailText} >{loc.t(texts.type)}{character.type}</Text>
                <Text style={styles.detailText} >{loc.t(texts.origin)}{character.origin.name}</Text>
                <Text style={styles.detailText} >{loc.t(texts.location)}{character.location.name}</Text>
            </View>
        </View>
    );
};

export default CharacterDetailScreen;

我检查了来自 API 的传入数据。是因为页面渲染时数据还没有来自api的错误吗?

这里来自 API 的传入数据示例:

const character = {
    "created": "2017-12-01T10:32:08.340Z", 
    "episode": ["https://rickandmortyapi.com/api/episode/5"], 
    "gender": "Male", 
    "id": 89, 
    "image": "https://rickandmortyapi.com/api/character/avatar/89.jpeg", 
    "location": {"name": "Giant's Town", "url": "https://rickandmortyapi.com/api/location/14"}, 
    "name": "Dale", 
    "origin": {"name": "Giant's Town", "url": "https://rickandmortyapi.com/api/location/14"}, 
    "species": "Mythological Creature", 
    "status": "Dead", 
    "type": "Giant", 
    "url": "https://rickandmortyapi.com/api/character/89"
}

4

1 回答 1

1

解决此问题的简单方法是预先定义您的数据:

const [character, setCharacter] = useState({
    "created": "", 
    "episode": [], 
    "gender": "", 
    "id": 0, 
    "image": undefined, 
    "location": {"name": "", "url": ""}, 
    "name": "", 
    "origin": {"name": "", "url": ""}, 
    "species": "", 
    "status": "", 
    "type": "", 
    "url": ""
})

这样您就不必再猜测是否定义了字符上的属性,并且您不必为可能使用的字符上的每个参数添加空检查而头疼。

解决此问题的另一种方法是将默认字符设置为 null 并有条件地呈现 ui

const CharacterDetailScreen = (props) => {

    const { styles, colors } = useThemedValues(getStyles);
    const loc = useLocalization();

    **// state for character detail**
    const [character, setCharacter] = useState(null])

    **// this id come from previous screen**
    const { characterId } = props.route.params

    useEffect(()=>{
        Axios.get('character/'+characterId)
            .then(response =>{
                characterDetail = response.data
                setCharacter(characterDetail)
                console.log(characterDetail.name) // if characterId=89, writes "dale" in console
            })
            .catch(error => {
                console.log(error)
            })
    },[])
 
    return (
        <View style={styles.container}>
            {character ? (
                <View style={styles.imageContainer}>
                    <Image source={{ uri: character.image }} style={styles.image}/>
                </View>
                <View style={styles.characterNameContainer}>
                    <Text style={styles.characterName}>{character.name}</Text>
                </View>
                <View style={styles.detailContainer}>
                    <Text style={styles.detailText} >{loc.t(texts.status)}{character.status}</Text>
                    <Text style={styles.detailText} >{loc.t(texts.species)}{character.species}</Text>
                    <Text style={styles.detailText} >{loc.t(texts.gender)}{character.gender}</Text>
                    <Text style={styles.detailText} >{loc.t(texts.type)}{character.type}</Text>
                    <Text style={styles.detailText} >{loc.t(texts.origin)}{character.origin.name}</Text>
                    <Text style={styles.detailText} >{loc.t(texts.location)}{character.location.name}</Text>
                </View>
            ) : (
                <Loading/>
            )}
        </View>
    );
};

export default CharacterDetailScreen;
于 2021-07-05T06:30:15.890 回答