Simon
Simon

Reputation: 537

React pass API data to chart

Background

For reference;

  const [chrtState, setChrtState] = useState({
    loading: false,
    chartos: null,
  });

  useEffect(() => {
    setChrtState({loading: true});
    const apiUrl = `http://example.com/api/request/`;
    axios
      .get(apiUrl, {
        withCredentials: true,
      })
      .then(res => {
        setChrtState({loading: false, repos: res.data.characters});
      });
  }, [setChrtState]);

  const setCanvas = name => {
    const apiUrl = `http://example.com/api/request/`;

    axios
      .get(apiUrl, {
        withCredentials: true,
      })
      .then(res => {
        setChrtState({loading: false, chartos: res.data.characters});
        //console.log(res.data.characters);
      });
  };

  return (
    <Line
      data={chartExample1[bigChartData + bigChartTime]}
      options={chartExample1.options}
      apiprops={chrtState.chartos}
    />
  );

Note: the data parameter is used to select a specific chart-type (e.g. data1, data2, etc), this part works fine and isn't related to the APIdata as such.

My Problem

I am struggling to work out how to pass the API data to the chart.js

I tried using some other examples of how to pass props but it is proving very confusing for me given that it is already passing data1: (canvas) etc.

What I've tried

  apiprops: (props) => {
    const {repos} = props;
    console.log(repos);
  },

but nothing was printed to the console for this.

I am very much still building my knowledge of reactjs so thank you for any help and guidance on this!

End goal

For reference, my end goal will be to pass the API data to the chart and then process each dictionary into the labels and the datasets.data - the API passes in this order

{
 "characters": [
    {
      "label": 123,
      "data": 321
    },
    {
      "label": 456,
      "data": 654
    }
  ]
}

Upvotes: 0

Views: 1755

Answers (1)

diedu
diedu

Reputation: 20825

I understood that you are trying to inject your API values into the existing functions in charts.js. First, you need to separate the API values into two arrays: labels and data. You can do that with reduce

  const values = res.data.characters.reduce(
    (acc, character) => ({
      labels: [...acc.labels, character.label],
      data: [...acc.data, character.data],
    }),
    { labels: [], data: [] }
  );
  setChrtState({ loading: false, repos: values });

To inject them into the functions, you'll need to modify the functions a little using currying

data1: ({labels, data}) => (canvas) => {
  ...

  return {
    labels,
    datasets: [
      {
        ...
        data,
      },
    ],
  };
},

and finally, call the function when passing the data prop to the Line component

<Line
  data={chartExample1[bigChartData + bigChartTime](chrtState.repos)}

Although looking at those functions they seem to have the same code, is just the data is changing, you could use a single function.

UPDATE

this would be the complete version of the component

  const [chrtState, setChrtState] = useState({
    loading: true,
    repos: null,
  });

  useEffect(() => {
    setChrtState({ loading: true });
    const apiUrl = `http://example.com/api/request/`;
    axios
      .get(apiUrl, {
        withCredentials: true,
      })
      .then((res) => {
        const values = res.data.characters.reduce(
          (acc, character) => ({
            labels: [...acc.labels, character.label],
            data: [...acc.data, character.data],
          }),
          { labels: [], data: [] }
        );
        setChrtState({ loading: false, repos: values });
      });
  }, [setChrtState]);

  if (chrtState.loading) {
    return <span>Loading</span>;
  }

  return (
    <Line
      data={chartExample1[bigChartData + bigChartTime](chrtState.repos)}
      options={chartExample1.options}
    />
  );

Upvotes: 1

Related Questions