thereactnoob
thereactnoob

Reputation: 31

State doesn't change in react

I made a promise function to get a JSON file from the official NBA API. In this function I'm trying to update a usestate, but I keep getting an empty array after setting the state. What am I overlooking?

const Games = () => {
    const [gameData, setGameData] = useState([]);
    const { readableDate } = useContext(NBAContext);

    const insertTime = readableDate.split('/');


        useEffect(() => {
            const jsonSrc = `https://cors-anywhere.herokuapp.com/http://data.nba.net/10s/prod/v1/${insertTime[2]}${insertTime[1]}${insertTime[0]}/scoreboard.json`;

            const getScores = async () => {
                        const response = await fetch(jsonSrc);
                        return await response.json()
                };

            getScores().then((result) => {
                console.log(result)
                setGameData(result);
                console.log(gameData);
            });

        }, [readableDate])

Upvotes: 1

Views: 83

Answers (2)

Tom Oakley
Tom Oakley

Reputation: 6403

edit: actual answer - setting state, whether with this.setState or the useState hook, is an asynchronous process. This means that calling console.log(gameData) right after setGameData(results) will result in the previous result (in this case, empty array). If you want to access gameData variable with results of the API call, use another useEffect hook with gameData as a dependency:

useEffect(() => {
  console.log(gameData)
}, [gameData])

initial answer, code improvement/advice: remove the line where you wrap the code inside getScores in a promise, and just return the result of await response.json().

useEffect(() => {
  const jsonSrc = `https://cors-anywhere.herokuapp.com/http://data.nba.net/10s/prod/v1/${insertTime[2]}${insertTime[1]}${insertTime[0]}/scoreboard.json`;

  const getScores = async () => {
    try {
      const response = await fetch(jsonSrc);
      return await response.json()
    } catch (err) {
      console.log(err)
      throw err
    }
  }

   getScores().then((result) => {
     console.log(result)
     setGameData(result.games);
   });
}, [readableDate])

Upvotes: 0

Domino987
Domino987

Reputation: 8774

Just like setState, the setting of useState is also asynchronous. That's why the console.log(gameData) prints the empty array. Since its still the previous array.

After the setting of the data, a new render will be called with the updated data and you can display it.

Upvotes: 0

Related Questions