Home > Mobile >  Why is it not filling the useState whin i get the data?
Why is it not filling the useState whin i get the data?

Time:05-02

I folowed tthis page: https://blog.logrocket.com/using-chart-js-react/ The data is loaded into the data and I see in console but the data is not loaded into the useState

import React, { useEffect, useState } from "react";
import budgetApi from "../api/budgetApi";
import { Bar } from "react-chartjs-2";
const BarChart = () => {
  const [chartData, setChartData] = useState({});

  useEffect(() => {
    getDataFromChart();
  }, []);

  const getDataFromChart = async () => {
    try {
      const response = await budgetApi.getByCategory();
      const data = response.data;
      setChartData({
        labels: [data.map((budget) => budget.category)],
        datasets: [
          {
            label: "Forint",
            data: [data.map((budget) => budget.total_amount)],
            backgroundColor: ["#ffbb11", "#ecf0f1", "#50AF95"],
            borderWidth: 1,
          },
        ],
      });
      console.log(chartData); //Empty!
    } catch (error) {
      console.log(error);
    }
  };
  return (
    <div>
      {
        <Bar
          data={chartData}
          options={{
            plugins: {
              title: {
                display: true,
                text: "Cryptocurrency prices",
              },
              legend: {
                display: true,
                position: "bottom",
              },
            },
          }}
        />
      }
    </div>
  );
};

export default BarChart;

I get some errors for example: can't access property "map", nextDatasets is undefined I think I get it because the chartData is empty.

Please help. Thanks for the answers

CodePudding user response:

const [chartData, setChartData] = useState({});

You've set your initial state to be an empty object. On your first render, you are passing that empty object to <Bar data={chartData}>. <Bar> doesn't expect an empty object, so it throws an exception on this line of code.

You do eventually load data, but the error happened before then. So while you are waiting for the data to load you need to either not render the bar chart at all, or pass it in enough dummy data data that it can do its job. For example:

const [chartData, setChartData] = useState(null); // null is easier to check for than {}

// ...

return (
  <div>
    {!chartData ? (
      <span>Loading...</span>
    ) : (
      <Bar
        data={chartData}
        options={{
        // etc
      />

    )}
  </div>
);

console.log(chartData); //Empty!

This log statement is leading you astray. This will always show the old chart data, even though you've successfully set state. If you want to verify that your component is rerendering, then put your log statement in the body of the component (you will still need to fix the issue i mentioned at the top)

See this question for more information about why this log statement doesn't work: The useState set method is not reflecting a change immediately

CodePudding user response:

You are not getting the data in console.log since setChartData does change the state, but the changed state is not still available on the next row.

You are getting the error since, at the very beginning, before the data is loaded in the object after the asynchronous call, the object is {}, so it is empty and does not have any key.

You should avoid to display the Bar component before data is loaded, so you can put a loading state or check any key you are expecting in the object, like

if (chartData.data) {
  return <Bar />; // With the props you need
}
return <></>;
  • Related