简体   繁体   中英

How do I mutate Chart.js data using React state?

In my project I wish to toggle between two sets of data: total hours worked each day in current week, and total hours worked each month in the current year. I am able to achieve Chart.js label manipulation in my button handlers, but I am unable to modify the state's data property. What am I missing here? Thank you for helping.

Note: The commented code produce this error statement when uncommented: Uncaught TypeError: nextDatasets.map is not a function

LineChart.js

  const [userData, setUserData] = useState({
    labels: Object.keys(daysData),
    datasets: [
      {
        label: "Hours worked",
        data: Object.values(daysData),
        backgroundColor: "red",
        borderColor: "black",
        borderWidth: 2,
      },
    ],
  });

  const onShowWeeklyHandler = () => {
    setUserData({ labels: Object.keys(daysData) });
    // setUserData({ datasets: { data: Object.keys(daysData) } });
  };

  const onShowMonthlyHandler = () => {
    setUserData({ labels: Object.keys(monthsData) });
    // setUserData({ datasets: { data: Object.keys(monthsData) } });
  };

You may be encountering issues because you are trying to shallow merge state with the useState hook. React does not support this. See this answer for more info.

If that does not solve your issue, have you looked into react-chartjs-2 ? You might be able to achieve what you want doing something like the following.

In your parent component (the one that contains the chart):

import { Bar } from "react-chartjs-2"; // import whatever chart type you need
...

const [userData, setUserData] = useState({
    labels: Object.keys(daysData),
    datasets: [
      {
        label: "Hours worked",
        data: Object.values(daysData),
        backgroundColor: "red",
        borderColor: "black",
        borderWidth: 2,
      },
    ],
  });

Then your handlers can be:

  const onShowWeeklyHandler = () => {
    setUserData({
      ...userData,
      datasets: {
        ...userData.datasets,
        labels: Object.keys(daysData),
        data: Object.values(daysData),
      },
    });
  };

  const onShowMonthlyHandler = () => {
    setUserData({
      ...userData,
      datasets: {
        ...userData.datasets,
        labels: Object.keys(monthsData),
        data: Object.values(monthsData),
      },
    });
  };

Finally:

return <Bar data={userData.datasets} />; // adapt for whatever chart type you need

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM