SoF
SoF

Reputation: 787

React Native- Can't rendering data from API on the screen

On the previous screen, you can choose an episode. On this screen, episode ID coming from the previous screen and with this ID, its taking every character ID from API. Characters IDs are slicing from characters URLs. You can see details that in the episode data example. When this screen rendering, there is no error and there is no character name on the flatlist. How can I solve this problem?

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

Here codes:

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;

Episode data example:

{
    "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"
}

Character data example:

{
    "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"
}

Upvotes: 1

Views: 195

Answers (1)

Apperside
Apperside

Reputation: 3602

When you call the endpoint 'character/' + id, the shape of the object you get is this

{
    "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"
}

As you can see this is not an array, but an object which contains an array of episodes.

Inside your function takeCharacters, you call setCharacterList(characterDetail) , where characterDetail is the response from your api, which, is I said, is not an array, that's why you see nothing (a FlatList wants an array to render).

If you look carefully at the shape of the api's data, you have:

  • the endpoint that gives you a list of episodes, where every episode object contains a list of charachert, but you have only the link
  • the endpoint that gives you the informations about a SINGLE episode.

I suggest you to do something like this (I didn't test it, but it should work, just wanted to suggest you the Promise.all() pattern)

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: this is not related to your problem, but I suggest to replace this

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

with this

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

it more reliable since it does not depend by the url's length

Upvotes: 2

Related Questions