2

Okay, so my problem is that I'm trying to modify an array after fetching JSON and storing as an array with hooks. How would I go about doing that?

I tried using another .then and calling the function I want to call, but when logging the array to the console in the function it just gives me an "cannot read property of description undefined error" Any help? Thanks!

const [repos, setRepos] = useState([]);
const [isLoaded, setIsLoaded] = useState(false);
const [error, setError] = useState(null);

function updateDates() {
    var i;
    console.log(repos[1].description);
}

// fetch github repo sorted by updated date and store in repos
useEffect(() => {
    fetch("https://api.github.com/users/benngagne/repos?sort=updated")
    .then(res => res.json())
    .then(
        (result) => {
            setRepos(result);
            setIsLoaded(true);
        },
        
        (error) => {
            setIsLoaded(true);
            setError(error);
        }
        )
    // .then(() => {
    //     updateDates();
    // })
    }, [])
benngagne
  • 23
  • 3
  • `useState`'s setter [doesn't immediately change the value](https://stackoverflow.com/q/54069253/996081). That's probably the issue you ran into. You could do your processing in the `.then()` which does `setRepos()`. – cbr Jan 15 '21 at 00:32
  • If you want to do something in reaction to a state change, use `useEffect`. Have the effect call the `updateDates` function, and have `repos` in its dependency array. That way the `repos` state will be populated before the `updateDates` function is called – Jayce444 Jan 15 '21 at 00:34

2 Answers2

1

Updating state is asynchronous, and you are trying to access updated state data immediately after state updating function(setRepos()).

useEffect hook is what you should be looking for. Set dependency array of useEffect to your state, so it will only work when your state changes. There, you can do your manipulations of your new state, do functions etc.

useEffect(() => {
    if(repos){ //checking if state is not null; to not catch initial state.
    //Do your functions, calculations etc..
    }
},[repos]);
Emre A
  • 240
  • 1
  • 6
0

how are you?

Your code has an error in your fetch, I'm adding those corrections and also a full class showing how to rander the incomming data. btw I just showing the full_name property from the response, but you can also grab all, like:

const {full_name,description} = repo;

Here's the full class:

import React, {useState, useEffect} from 'react'

function App() {
  const [repos, setRepos] = useState([]);
  const [isLoaded, setIsLoaded] = useState(false);
  const [error, setError] = useState(null);

// fetch github repo sorted by updated date and store in repos

useEffect(() => {
fetch("https://api.github.com/users/benngagne/repos?sort=updated")
.then(res => res.json())
.then(result => {
        setRepos(result);
        setIsLoaded(true);
    })
.catch((error) => {
        setIsLoaded(true);
        setError(error);
    })
}, [])

 return (
    <div>
      {
        repos.map((repo, idx) => {
          const {full_name} = repo;
          return <div>{full_name}</div>
         })
      }
    </div>
  )
}

export default App
Andre Moraes
  • 379
  • 1
  • 8