issue with rendering the React-native flatList

Viewed 363

Good afternoon StackOverflowers I'm working on building a RssFeeder app in order to work on my React Native skills but somehow ran into a problem which I wanted to fix now, as I try to render my objects which I get from an outside API called newsAPI and I try to show them into a flatList which for some reason doesn't work as I hope; here is my HomeScreen part for the flatList:

 return (
    <View>
      <Text>We have found {articles?.length} articles</Text>
      <FlatList
        data={articles}
        showsHorizontalScrollIndicator={false}
        horizontal
        scrollEnabled
        keyExtractor={(articles) => articles?.name}
        extraData={articles} 
        renderItem={({ item }) => {
          return (
            <TouchableOpacity onPress={() => navigation.navigate("Detail")}>
              <DetailScreen result={item} />
            </TouchableOpacity>

         
          );
        }}
      ></FlatList>

I'm pretty sure that API works properly cause the first line which shows the length of the articles shows the exact number, in addition, I added a Text component after <DetailScreen result={item} /> and it shows me Text components 10 times, so I wonder what is the problem with the code.

result in the <DetailScreen result={item} /> is a madeup prop for my second screen called 'DetailScreen' to carry all the data from Home to DetailScreen.

Also, this is what DetailScreen looks like at the moment.

import React from "react";
import { Text, View, StyleSheet } from "react-native";
import HomeScreen from "./HomeScreen";

const DetailScreen = (result) => {
  return (
    <View>
      <Text>{result.title}</Text>
    </View>
  );
};

const styles = StyleSheet.create({});

export default DetailScreen;

This is a sample from the API:

{ "source": { "id": "techcrunch", "name": "TechCrunch" }, "author": "Jonathan Shieber", "title": "How did Atlanta become a top breeding ground for billion-dollar startups in the Southeast?", "description": "Over the past five years, the Southeastern region, led by Atlanta, has gone from being “one of the best kept secrets” in tech, to a vibrant ecosystem teeming with a herd of the billion dollar tech businesses that are referred to in the investment world as “un…", "url": "https://techcrunch.com/2021/05/02/how-did-atlanta-become-a-top-breeding-ground-for-billion-dollar-startups-in-the-southeast/", "urlToImage": "https://techcrunch.com/wp-content/uploads/2018/06/GettyImages-467404053.jpg?w=600", "publishedAt": "2021-05-02T15:25:38Z", "content": "Over the past five years, the Southeastern region, led by Atlanta, has gone from being “one of the best kept secrets” in tech, to a vibrant ecosystem teeming with a herd of the billion dollar tech bu… [+18425 chars]" },

2 Answers

As pointed out by others and me in the comments There are 2 syntax issues

  1. Change articles?.name to articles.name in the keyExtractor
  2. Destructure the props correctly in DetailScreen from (result) to ({result}) Both these are important for your code to work correctly.

Lastly, I noticed your articles data is an object {} while data in FlatList must be an array []. So please transform the article data you are receiving from the API into an array and it will work. Link to React Native official docs where you will see FlatList only accepts array in the data prop.

Here is the link to codesandbox where you will see I transformed your articles object data into updatedArticles array and passed the updatedArticles into the FlatList and it is rending it correctly.

I found the solution which is depend on the version of react-navigation that you are using the way that you can pass the parameters to others screens will change eventually because I'm using react navigation V5 and by considering this link https://reactnavigation.org/docs/params I should pass the params in this way in comparison with the

<TouchableOpacity onPress={() => navigation.navigate("Detail")}>
              <DetailScreen result={item} />
            </TouchableOpacity>

To be honest that's a bit weird, why we need to change way we code depend on the version of react navigation :p

   <View>
     <Text>We have found {articles?.length} articles</Text>
     <FlatList
       data={articles}
       showsHorizontalScrollIndicator={false}
       // horizontal
       scrollEnabled
       keyExtractor={(articles) => articles?.title}
       extraData={articles} //makes flatList to re-render each time articles changes.
       renderItem={({ item }) => {
         //renderItem takes 'objects' from 'data' (data and item are keyWords for flatLists)
         return (
           <TouchableOpacity
             style={{ marginTop: 20 }}
             onPress={() =>
               navigation.navigate("Detail", {
                 article: item, //in navigation V5 we use this method to pass the chosen params(item) by setting a chosen name to mentioned screen("Detail") then we use useRoute to capture those.
               })
             }
           >
             {/* <DetailScreen result={item} /> */}
             <Text>{item.title}</Text>
           </TouchableOpacity>

           //<Text>{item?.title}</Text>
         );
       }}
     ></FlatList>

If you didn't understand the code properly try to focus on the comments that I put in the code.

Related