How to map nested JSON properties collected with JS fetch API and SWR

Viewed 426

I have following JSON API, permanently provided by the Swiss Government.

https://www.bfs.admin.ch/bfsstatic/dam/assets/14856203/master

I am trying to list some content that does not appear in the first level – in my case some voting statistics (jaStimmenInProzent) of every vote (vorlagenId):

Screenshot API

I am using fetch API and Vercel SWR. Unfortunately I couldn’t find a tutorial/example where the content that is mapped does not appear on the first level. Any Idea how to proceed and getting the vorlagen array listed? I tried following without success (see sandbox):

import useSWR from "swr";
import "./styles.css";

const fetcher = (...args) => fetch(...args).then((response) => response.json());

export default function App() {
  const { data, error } = useSWR(
    "https://app-prod-static-voteinfo.s3.eu-central-1.amazonaws.com/v1/ogd/sd-t-17-02-20201129-eidgAbstimmung.json",
    fetcher
  );

  if (error) return <h1>this is an error: {error}</h1>;

  return (
    <div className="App">
      {data ? (
        data.map((vorlagen) => <h1>{vorlagenId}</h1>)
      ) : (
        <h1>loading...</h1>
      )}
    </div>
  );
}

2 Answers

Your data contains schweiz property which includes vorlgen property which is an array. You won't be able to map directly on your data.

You'd have to map over data.schweiz.vorlagen which will eventually give you access to the required subproperties.

{data ? (
    data.schweiz.volragen.map((vorlagen) => (
      <div>
        <h1>{vorlgen.vorlagenId}</h1>
        <h4>{volragen.resultat.jaStimmenInProzent}</h4>
      </div>
    ))
  ) : (
  <h1>loading...</h1>
)}

assuming that the JSON file at the top is the whole thing at the URL, then you just aren't accessing it right, here is an example

import useSWR from "swr";
import "./styles.css";

const fetcher = (...args) => fetch(...args).then((response) => response.json());

export default function App() {
  const { data, error } = useSWR(
    "https://app-prod-static-voteinfo.s3.eu-central-1.amazonaws.com/v1/ogd/sd-t-17-02-20201129-eidgAbstimmung.json",
    fetcher
  );

  if (error) return <h1>this is an error: {error}</h1>;
   

  return (
    <div className="App">
      {data ? (
        data.schwiez.vorlagen.map((value) => <h1>{value.vorlagenId}</h1><p>{value.resultat.jaStimmenInProzent}</p>)
      ) : (
        <h1>loading...</h1>
      )}
    </div>
  );
}

thought really you want to only download the data you're going to access so if you have control over the server you download it from, consider adding a function that maps it server-side and before sending it (only if you arent using some of the data of course).

Im no god but in theory this should work (I haven't tested it)

sorry for any typos in the spelling of the values

Related