【问题标题】:React Native - "Undefined is not an object" error when render a screen that take data from APIReact Native - 渲染从 API 获取数据的屏幕时出现“未定义不是对象”错误
【发布时间】:2021-09-15 22:33:57
【问题描述】:

我是 React Native 的新手。我正在制作一个从 API 获取数据并将其显示在屏幕上的应用程序。呈现此屏幕时会出现以下错误: 渲染错误 undefined 不是对象(评估 '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"
}

【问题讨论】:

  • 这是因为 setCharacter(characterDetail) 是异步过程,将数据设置为状态需要时间。您面临的错误是因为“字符”状态为空。
  • 你应该在角色有一些数据时加载视图。添加逻辑以仅在数据可用字符时显示视图。

标签: javascript react-native api axios react-flatlist


【解决方案1】:

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

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

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

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

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;

【讨论】:

  • 成功了!太感谢了!您对解决“source.uri 不应为空屏”警告有什么建议吗?
  • 是的,使用 undefined 而不是空字符串,或者您可以使用默认图像预先填充它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-13
  • 2021-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-30
  • 1970-01-01
相关资源
最近更新 更多