首页 > 解决方案 > React Native - 无法在屏幕上呈现来自 API 的数据

问题描述

在上一个屏幕上,您可以选择一集。在这个屏幕上,剧集 ID 来自前一个屏幕,使用这个 ID,它会从 API 中获取每个角色 ID。字符 ID 是从字符 URL 中切分出来的。您可以在剧集数据示例中查看详细信息。在这个画面渲染的时候,没有报错,flatlist上也没有字符名。我怎么解决这个问题?

API:https ://rickandmortyapi.com/api/

这里代码:

const EpisodeDetailScreen = (props) => {

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

    // character list for flatlist
        const [characterList, setCharacterList] = useState([
    {
        "created": "",
        "episode": [""],
        "gender": "",
        "id": 0,
        "image": "",
        "location": { "name": "", "url": "" },
        "name": "",
        "origin": { "name": "", "url": "" },
        "species": "",
        "status": "",
        "type": "",
        "url": ""
    },
])

    // episode details
    const [episodeDetail, setEpisodeDetail] = useState([])


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

    // details of a chosen episode from the previous screen
    useEffect(() => {
        Axios.get('episode/' + episodeId)
            .then(response => {
                let episodeDetail = response.data
                setEpisodeDetail(episodeDetail) // episode details

                //Getting the IDs of the characters in the section from the last part of the URLs in the incoming data
                // You can see in data example that
                for (var i = 0; i < episodeDetail.characters.length; i++) {
                    var charactersUrlInEpisode = episodeDetail.characters[i]
                    var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)

                    // Extracting character ids and character details from API and throwing them into state
                    takeCharacters(charactersIdInUrl)
                    console.log(charactersIdInUrl) // I can see the correct IDs
                }
            })
            .catch(error => {
                console.log(error)
            })

    }, [])

    // function that pulls character details from api based on given id
    const takeCharacters = (id) => {
        Axios.get('character/' + id)
            .then(response => {
                let characterDetail = response.data
                setCharacterList(characterDetail)
                console.log(characterDetail) // I can see characters data on console
            })
            .catch(error => {
                console.log(error)
            })
    }

    const _renderCharactersItem = ({ item }) => {
        console.log('flatlist')  // its working but flatList not rendering anything
        return (
            <TouchableOpacity onPress={() => {
                props.navigation.navigate("character-detail-screen", {
                    characterId: item.id
                });
            }}>
                    <View style={styles.characterButton}>
                    <Text style={styles.characterNameText} numberOfLines={1}>{item.name}</Text>
                </View>
            </TouchableOpacity>
        )
    }

    return (
        <View style={styles.container}>
            <View style={styles.episodeNameContainer}>
                <Text style={styles.episodeNameText}>{episodeDetail.name}</Text>
            </View>
            <View style={styles.detailsContainer}>
                <Text style={styles.detailsText}>{loc.t(texts.episode)}{episodeDetail.episode}</Text>
                <Text style={styles.detailsText}>{loc.t(texts.airDate)} {episodeDetail.air_date}</Text>
            </View>
            <View style={styles.characterTitleContainer}>
                <Text style={styles.characterTitleText}>{loc.t(texts.characters)}</Text>
            </View>
            <FlatList
                data={characterList}
                renderItem={_renderCharactersItem}
                keyExtractor={item => item.id}
                style={styles.flatListContainer}
            />
        </View>
    );
};

export default EpisodeDetailScreen;

剧集数据示例:

{
    "id": 1,
    "name": "Pilot",
    "air_date": "December 2, 2013",
    "episode": "S01E01",
    "characters": [
        "https://rickandmortyapi.com/api/character/1",
        "https://rickandmortyapi.com/api/character/2",
        "https://rickandmortyapi.com/api/character/35",
        "https://rickandmortyapi.com/api/character/38",
        "https://rickandmortyapi.com/api/character/62",
        "https://rickandmortyapi.com/api/character/92",
        "https://rickandmortyapi.com/api/character/127",
        "https://rickandmortyapi.com/api/character/144",
        "https://rickandmortyapi.com/api/character/158",
        "https://rickandmortyapi.com/api/character/175",
        "https://rickandmortyapi.com/api/character/179",
        "https://rickandmortyapi.com/api/character/181",
        "https://rickandmortyapi.com/api/character/239",
        "https://rickandmortyapi.com/api/character/249",
        "https://rickandmortyapi.com/api/character/271",
        "https://rickandmortyapi.com/api/character/338",
        "https://rickandmortyapi.com/api/character/394",
        "https://rickandmortyapi.com/api/character/395",
        "https://rickandmortyapi.com/api/character/435"
    ],
    "url": "https://rickandmortyapi.com/api/episode/1",
    "created": "2017-11-10T12:56:33.798Z"
}

字符数据示例:

{
    "id": 1,
    "name": "Rick Sanchez",
    "status": "Alive",
    "species": "Human",
    "type": "",
    "gender": "Male",
    "origin": {
        "name": "Earth (C-137)",
        "url": "https://rickandmortyapi.com/api/location/1"
    },
    "location": {
        "name": "Earth (Replacement Dimension)",
        "url": "https://rickandmortyapi.com/api/location/20"
    },
    "image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
    "episode": [
        "https://rickandmortyapi.com/api/episode/1",
        "https://rickandmortyapi.com/api/episode/2",
        "https://rickandmortyapi.com/api/episode/3",
        "https://rickandmortyapi.com/api/episode/4",
        "https://rickandmortyapi.com/api/episode/5",
        "https://rickandmortyapi.com/api/episode/6",
        "https://rickandmortyapi.com/api/episode/7",
        "https://rickandmortyapi.com/api/episode/8",
        "https://rickandmortyapi.com/api/episode/9",
        "https://rickandmortyapi.com/api/episode/10",
        "https://rickandmortyapi.com/api/episode/11",
        "https://rickandmortyapi.com/api/episode/12",
        "https://rickandmortyapi.com/api/episode/13",
        "https://rickandmortyapi.com/api/episode/14",
        "https://rickandmortyapi.com/api/episode/15",
        "https://rickandmortyapi.com/api/episode/16",
        "https://rickandmortyapi.com/api/episode/17",
        "https://rickandmortyapi.com/api/episode/18",
        "https://rickandmortyapi.com/api/episode/19",
        "https://rickandmortyapi.com/api/episode/20",
        "https://rickandmortyapi.com/api/episode/21",
        "https://rickandmortyapi.com/api/episode/22",
        "https://rickandmortyapi.com/api/episode/23",
        "https://rickandmortyapi.com/api/episode/24",
        "https://rickandmortyapi.com/api/episode/25",
        "https://rickandmortyapi.com/api/episode/26",
        "https://rickandmortyapi.com/api/episode/27",
        "https://rickandmortyapi.com/api/episode/28",
        "https://rickandmortyapi.com/api/episode/29",
        "https://rickandmortyapi.com/api/episode/30",
        "https://rickandmortyapi.com/api/episode/31",
        "https://rickandmortyapi.com/api/episode/32",
        "https://rickandmortyapi.com/api/episode/33",
        "https://rickandmortyapi.com/api/episode/34",
        "https://rickandmortyapi.com/api/episode/35",
        "https://rickandmortyapi.com/api/episode/36",
        "https://rickandmortyapi.com/api/episode/37",
        "https://rickandmortyapi.com/api/episode/38",
        "https://rickandmortyapi.com/api/episode/39",
        "https://rickandmortyapi.com/api/episode/40",
        "https://rickandmortyapi.com/api/episode/41"
    ],
    "url": "https://rickandmortyapi.com/api/character/1",
    "created": "2017-11-04T18:48:46.250Z"
}

标签: javascriptreact-nativeapiaxiosreact-native-flatlist

解决方案


当你调用端点'character/' + id时,你得到的对象的形状是这样的

{
    "id": 1,
    "name": "Rick Sanchez",
    "status": "Alive",
    "species": "Human",
    "type": "",
    "gender": "Male",
    "origin": {
        "name": "Earth (C-137)",
        "url": "https://rickandmortyapi.com/api/location/1"
    },
    "location": {
        "name": "Earth (Replacement Dimension)",
        "url": "https://rickandmortyapi.com/api/location/20"
    },
    "image": "https://rickandmortyapi.com/api/character/avatar/1.jpeg",
    "episode": [
        "https://rickandmortyapi.com/api/episode/1",
        "https://rickandmortyapi.com/api/episode/2",
        "https://rickandmortyapi.com/api/episode/3",
        "https://rickandmortyapi.com/api/episode/4",
        "https://rickandmortyapi.com/api/episode/5",
        "https://rickandmortyapi.com/api/episode/6",
        "https://rickandmortyapi.com/api/episode/7",
        "https://rickandmortyapi.com/api/episode/8",
        "https://rickandmortyapi.com/api/episode/9",
        "https://rickandmortyapi.com/api/episode/10",
        "https://rickandmortyapi.com/api/episode/11",
        "https://rickandmortyapi.com/api/episode/12",
        "https://rickandmortyapi.com/api/episode/13",
        "https://rickandmortyapi.com/api/episode/14",
        "https://rickandmortyapi.com/api/episode/15",
        "https://rickandmortyapi.com/api/episode/16",
        "https://rickandmortyapi.com/api/episode/17",
        "https://rickandmortyapi.com/api/episode/18",
        "https://rickandmortyapi.com/api/episode/19",
        "https://rickandmortyapi.com/api/episode/20",
        "https://rickandmortyapi.com/api/episode/21",
        "https://rickandmortyapi.com/api/episode/22",
        "https://rickandmortyapi.com/api/episode/23",
        "https://rickandmortyapi.com/api/episode/24",
        "https://rickandmortyapi.com/api/episode/25",
        "https://rickandmortyapi.com/api/episode/26",
        "https://rickandmortyapi.com/api/episode/27",
        "https://rickandmortyapi.com/api/episode/28",
        "https://rickandmortyapi.com/api/episode/29",
        "https://rickandmortyapi.com/api/episode/30",
        "https://rickandmortyapi.com/api/episode/31",
        "https://rickandmortyapi.com/api/episode/32",
        "https://rickandmortyapi.com/api/episode/33",
        "https://rickandmortyapi.com/api/episode/34",
        "https://rickandmortyapi.com/api/episode/35",
        "https://rickandmortyapi.com/api/episode/36",
        "https://rickandmortyapi.com/api/episode/37",
        "https://rickandmortyapi.com/api/episode/38",
        "https://rickandmortyapi.com/api/episode/39",
        "https://rickandmortyapi.com/api/episode/40",
        "https://rickandmortyapi.com/api/episode/41"
    ],
    "url": "https://rickandmortyapi.com/api/character/1",
    "created": "2017-11-04T18:48:46.250Z"
}

如您所见,这不是一个数组,而是一个包含剧集数组的对象。

在你的函数内部takeCharacters,你调用setCharacterList(characterDetail),你的 api 的响应在哪里characterDetail,我说过,它不是一个数组,这就是你什么都看不到的原因(aFlatList想要一个数组来渲染)。

如果你仔细查看 api 数据的形状,你有:

  • 为您提供剧集列表的端点,其中每个剧集对象都包含一个字符列表,但您只有链接
  • 为您提供有关单集的信息的端点。

我建议你做这样的事情(我没有测试它,但它应该可以工作,只是想建议你 Promise.all() 模式)

const promises = []

        for (var i = 0;i < episodeDetail.characters.length;i++) {
            var charactersUrlInEpisode = episodeDetail.characters[i]
            var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)

            // Build a promise array to get the characters one by one
            // takeCharacters(charactersIdInUrl)
            promises.push(const promise = Axios.get('character/' + charactersIdInUrl);)
            console.log(charactersIdInUrl) // I can see the correct IDs
        }
        Promise.all(promises)
            .then((data) => {
                // data should be an array that you can set as FlatList's data
                console.log("fetched data", data);
            })

PS:这与你的问题无关,但我建议更换这个

var charactersIdInUrl = charactersUrlInEpisode.slice(42, charactersUrlInEpisode.length)

有了这个

cost splittedUrl=charactersUrlInEpisode.split("/");
var charactersIdInUrl = splittedUrl[splittedUrl-length - 1]

它更可靠,因为它不依赖于 url 的长度


推荐阅读