API Call React, problems with Accessing Data

Viewed 305

first of all, i have to say that i´m quiet new to javascript and Frontend, especially with React.

I try to do an API-Call to get the JSON and to display it via React. I´m using a material-ui template which just needs the informations for the display in form of two arrays, one for the data and one for the headers.

I would like to get the "name" Properties of the JSON into one of this arrays.

I wrote a state with the useState() function. Inside the (fetch.then(data) =>) i would like to assign the json from the api to the state value. But as i just want to print a part of the Json i tried to data.value[0].value, but it won´t work.

it says: "TypeError: data.holidays[i] is undefined" as i want to acess via data.holidays[i].name

 //Create State
  const [data, setData] = useState({
    holidays: [holiday],
  });

  const [holiday, setHoliday] = useState({
    id: "",
    logo: "",
    name: "",
  });

  fetch("http://localhost:8080/da-calendarific/api/regionGroup/all")
    .then((response) => response.json())
    .then((data) => {
      setData({ holidays: data });
    });

  //This should be the Output Array
  let returnvalue = new Array();

  var i;
  for(i = 0; i < data.holidays.length; i++) {
    returnvalue.push(data.holidays[i].name);
  }

JSON from API:

[
  {
    "id": 1,
    "name": "Europe\n"
  },
  {
    "id": 3,
    "logo": ".png\n",
    "name": "Asia\n"
  },
  {
    "id": 4,
    "logo": ".png\n",
    "name": "Australia\n"
  },
  {
    "id": 5,
    "logo": ".png\n",
    "name": "America\n"
  }
]
2 Answers

1/ Your fetch will be call every time you set a state, so you should add your fetch inside a useEffect and track only the state you want tit to refresh the fetch look at useEffect and specialy the "Tip: Optimizing Performance by Skipping Effects" . React COmponent refresh his content every time there is a value modified (a useState defined one), so you will send a request on each change (it is not what you want, and you can let the array of useEffect hok option empty to go for a one shot at loading page).

2/ You defined a useState for "data" and "setData" the wrong way (and also, before to define the holiday variable). You should initiate the real entry of the useState data at first (i mean, with a real value to set at initial time or nothing).

If you want something more dynamic and interact to each with other, you may have to look at the useReducer hook. It may interest you in your project.

The problem here is the placement of your code and in which order it will execute. React can seem weird at first if you are coming from vanilla JavaScript (it was for me anyway) - but once you learn all the ins-and-outs its the best!

The fetch request is a promise (meaning it will not return a value immediately but at some point in the future), this means the setData({ holidays: data }) is delayed and when you retrieve the data from the array data.holidays[i].name it does not exist yet.

The Fix? - Rearrange the code + set returnvalue as state + add the useEffect hook.

const [returnvalue, setReturnvalue] = useState([]);

useEffect(() => {
  fetch("http://localhost:8080/da-calendarific/api/regionGroup/all")
    .then((response) => response.json())
    .then((data) => {
      setData({ holidays: data });
    });
}, []); // <-- Note the empty brackets here

useEffect(() => {
  setReturnvalue(
    data.map(holiday => holiday.name);
  );
}, [data]); // <-- And here

Why does this work? - Adding the array data to the returnvalue only happens when there is a change to data, this way it does not run too early when the fetch has not finished.

The useEffect hook does not run until after the component is mounted Read more React UseEffect Hook Docu

Related