why this const is not getting value?

Viewed 59

I have this issue, I need to pass array values what I got from async function to objects to display it on a FlatList but I am not receiving any value on objects to put on data={objects} returns undefined. I tried to check if objects was getting any value, it only gets value if a put on data={loadData()} after 3 times loaded. Also this will call the function infinity times. this is my code

import React, { useState, useEffect } from 'react';
import { Text , TextInput, View, StyleSheet, FlatList } from 'react-native';
import  Object  from './Object';


export default function Content () {
  const [objects, setObjects] = useState([]);
    const [refreshing, setRefreshing] = useState(false);
    const [search, setSearch] = useState("");
  
  const loadData = async () => {
        const res = await fetch(
            "https://us.api.blizzard.com/data/wow/search/item?namespace=static-us&name.en_US=Thunderfury&orderby=id&_page=1&access_token=privateToken"
        );
        const data = await res.json();
    console.log('data: ', data);
        setObjects(data);
    console.log(objects);
    };

    useEffect(() => {
        loadData();
    
    }, []);
 
  
  return (
      <View style={styles.content}>
      <View style={styles.section} >
        <Text style={styles.logo}>Input </Text>
        <TextInput
                    style={styles.searchInput}
                    placeholder="Search an item"
                    placeholderTextColor="#858585"
                    onChangeText={(text) => text && setSearch(text)}
                />
        </View>

        
         <FlatList 
                    data={objects}
                showsVerticalScrollIndicator={false}
                renderItem={({ item }) => <Object object={item} style={styles.item}/>}
                refreshing={refreshing}
                onRefresh={ async () => {
          setRefreshing(true);
                    await loadData();
                    setRefreshing(false); 
        }}
            />
       
      </View>
     
  );
}

const styles = StyleSheet.create({
    content: {
    borderColor: 'black',
    display: 'flex',
    flexDirection: 'column',
    height: '85%',
    width: '100%',
    backgroundColor: '#fff',
    padding: 40,
    gap: 30,
  },
    section: {
        shadowRadius: '6px',
        borderColor: '#af9c81',
        height:  100,
        gap : 20,
        backgroundColor: 'white',
        width: '100%',
        borderRadius: '20px',
        shadowColor:'#af9c81',
        shadowOffset: {width: 0, height: 5},
        padding: 20,
    },
    section2: {
        shadowRadius: '6px',
        borderColor: '#af9c81',
        height:  400,
        backgroundColor: 'white',
        width: '100%',
        borderRadius: '20px',
        shadowColor:'#af9c81',
        shadowOffset: {width: 0, height: 5},
        padding: 20,
    }, 
    searchInput : {
      padding: 3,
    },
  }
);
1 Answers

Your code seems to work fine. The reason why console.log(objects) returns undefined is because it is run immediately after setObjects(data).

State updates in React are asynchronous, meaning that React does not wait for the state to be updated before executing the next line of code. In your case, the state update setObjects(data) is not finished before console.log(objects) is run, and therefore it returns undefined.

To print when objects is updated, you can use

  useEffect(() => {
    console.log("objects", objects);
}, [objects]);

Are you sure that you actually are getting any data from the endpoint? I have tried implementing your code with the endpoint https://hacker-news.firebaseio.com/v0/topstories.json, which seems to work.

import React, { useState, useEffect } from "react";
import { Text, TextInput, View, StyleSheet, FlatList } from "react-native";

export default function TabOneScreen() {
  const [objects, setObjects] = useState([]);
  const [refreshing, setRefreshing] = useState(false);
  const [search, setSearch] = useState("");

  const loadData = async () => {
    const res = await fetch(
      "https://hacker-news.firebaseio.com/v0/topstories.json"
    );
    const data = await res.json();
    console.log("data: ", data);
    setObjects(data);
  };

  useEffect(() => {
    console.log("objects", objects);
  }, [objects]);

  useEffect(() => {
    loadData();
  }, []);

  return (
    <View style={styles.content}>
      <View style={styles.section}>
        <Text style={styles.logo}>Input </Text>
        <TextInput
          style={styles.searchInput}
          placeholder="Search an item"
          placeholderTextColor="#858585"
          onChangeText={(text) => text && setSearch(text)}
        />
      </View>

      <FlatList
        data={objects}
        showsVerticalScrollIndicator={false}
        renderItem={({ item }) => <Text> {item} </Text>}
        refreshing={refreshing}
        onRefresh={async () => {
          setRefreshing(true);
          await loadData();
          setRefreshing(false);
        }}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  logo: {
    width: "100%",
  },
  content: {
    borderColor: "black",
    display: "flex",
    flexDirection: "column",
    height: "85%",
    width: "100%",
    backgroundColor: "#fff",
    padding: 40,
  },
  section: {
    borderColor: "#af9c81",
    height: 100,
    backgroundColor: "white",
    width: "100%",
    shadowColor: "#af9c81",
    shadowOffset: { width: 0, height: 5 },
    padding: 20,
  },
  section2: {
    borderColor: "#af9c81",
    height: 400,
    backgroundColor: "white",
    width: "100%",
    shadowColor: "#af9c81",
    shadowOffset: { width: 0, height: 5 },
    padding: 20,
  },
  searchInput: {
    padding: 3,
  },
});

Related