jsonreact-nativefetch-apireact-native-flatlistmap-function

FlatList is not working when iterating JSON


Currently I am trying to show the data served by an API and brought with fetch. But when deploying with FlatList I have the error:

"undefined is not an object (evaluating item.title)".

I have used JSON.stringify () and json.parse, I have also stopped using both and nothing, in any way it works. Please help. The current code is this:

const { height, width } = Dimensions.get('window');
var autorization = 'Basic asdfasdfasdf';
let url = 'https://www.pagetest/api/search';

export default class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoading: true,
            words: 'anyword',
            Loader: [],
            loadFlatList: false
        }
    }
    handlePress = async () => {
        fetch(url, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json; charset=utf-8',
                'Authorization': autorization
            },
            body: JSON.stringify({
                keyword: this.state.words,
            })
        })
            .then((response) => response.json())
            .then((responseJson) => {
                this.setState({
                    isLoading: false,
                    Loader: responseJson.movies,
                })
            })
            .catch((error) => {
                alert(error);
            })
            .done();
}
/**  Function that collects the text of onChangeText and makes changes in the states, 
also calls the function that contains the 'fetch' **/

handleSearch = (text) => {
    this.setState({ words: text, isLoading: false, loadFlatList: true });
/** Function that initiates the 'fet... */

    this.handlePress();
}

render() {
    return (

         /** Head icons a input search **/

        <View style={{ backgroundColor: '#181818', height: height }}>
            <View style={styles.containerHead}>
                <Image
                    source={BACK_ICON}
                    style={{ width: 40, height: 40, paddingRight: 3,               
                     paddingTop: 5 }} />

                <View style={styles.containerFrom}>
                    <Image
                        source={SEARCH_ICON}
                        style={{ width: height * .02, height: height 
                        * .02, opacity: .2 }} />
                    <TextInput style={styles.txtInput} placeholder= 
                         {'Searching'}
                        onChangeText={(text) => 
                        this.handleSearch(text)}
                    ></TextInput>
                </View>
            </View>

            {this.state.isLoading &&
                <View style={styles.bodyText}>
                    <Text style={styles.titleText}>
                        Find movies, series, directors, actors and...
                    </Text>
                </View>}

                /** Here the FlatList starts...  */
               
            <View style={styles.bodyText}>
                <ScrollView>
                    {this.state.Loader.length > 0 && <FlatList
                        data={this.state.Loader}
                        keyExtractor={(item) => item}
                        extraData={this.state}
                        renderItem={({ item }) => <View style={styles.bodyText}>
                            <Text style={styles.titleText}>{item.title}, {item.description}</Text>
                        </View>}
                    />}
                </ScrollView>
            </View>
        </View>
    );
}
}

const styles = StyleSheet.create({

titleText: {
    fontSize: 25,
    color: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    alignContent: 'center',

},
containerHead: {
    flexDirection: 'row',
    backgroundColor: '#000000',
    justifyContent: 'space-between',
    height: height * .05
},
containerFrom: {
    flexDirection: 'row',
    backgroundColor: '#000000',
    justifyContent: 'flex-end'
},
bodyText: {

    justifyContent: 'center'
},
});

I have made sure that when FlatList starts its work fetch fetched data is available in the state, for this I use {this.state.Loader>0 && ...} but it has not worked, neither has it worked with map. The JSON that I get from the API is like this:

{
    "keyword": " santo",
    "movies": [
        {
            "id": "116",
            "title": "El Milagro De Todos Los Santos",
            "description": "Cuando un grupo de refugiados birmanos se une a la congregación, el pastor de una iglesia anglicana que fracasa intenta ayudarlos plantando cosechas y buscando la ayuda de la comunidad.",
            "url": "https://www.pagetest.com/assets/video/705ae4c7b5e92a52cb9763ecb50b06d1.mp4",
            "url_en": "",
            "clasification": {
                "title": "A",
                "description": "Mayores de 6 años."
            },
            "year": "2017",
            "poster": "https://www.pagetest.com/assets/global/movie_poster/116.jpg",
            "thumbnail": "https://www.pagetest.com/assets/global/movie_thumb/116.jpg"
        },
        null
    ],
    "series": []
}

Any idea why neither FlatList nor map() are working here?


Solution

  • is because your second Item in the list is null. Your movies array has 2 elements, the second is null. Remove the null from your array and should work.

    renderItem={({ item }) => {
      if(item !== null) {
       return  <View style={styles.bodyText}>
                  <Text style={styles.titleText}>{item.title}, 
                  {item.description}</Text>
               </View>
          }
     }
    

    or better just clear your array before using it

    let filteredArray = arr.map((item) => {
        if(item !== null) {
             return item;
        } else {
             return false;
        }
    }).filter(Boolean);
    

    I prefer the second solution .