2
votes

I am trying to change Chart.js datasets when React-Select value change using useState in React Hooks.

console.log(event) inside handleChange function, I'm getting the desired result but to use it in the switch statement written below is the problem.

Reference code here - https://codesandbox.io/s/sparkling-morning-8lghs?file=/src/App.js:925-979

After adding onChange to React-Select and try to implement the logic to change chart datasets: https://codesandbox.io/s/hopeful-fog-55yv8?file=/src/App.js

how do I make use of the value I'm getting in the handleChange function in the switch statement?

import React, {useState, useEffect} from "react";
import Select from "react-select";
import {Bar} from "react-chartjs-2";
import axios from "axios";

const CanvasFour = () => { 
  const [chartData, setChartData] = useState({});
  const [userSelect, setUserSelect] = useState({});
  const [hour, setHour] = useState({});
  const [day, setDay] = useState({});
  const [data, setData] = useState({});
  let event;
  
  const getRandomColors = (numOfBars) => {
    const letters = "0123456789ABCDEF".split("");
    let colors = [];
    for(let i = 0; i < numOfBars; i++){
      let color = "#";
      for(let k = 0; k < 6; k++){
          color += letters[Math.floor(Math.random() * 16)]; 
      }
      colors.push(color)
    }
    return colors
  }

  const options=[
    {label:'last hour', value:'hour'},
    {label:'last day', value:'day'},
    {label:'last week', value:'week'},
    {label:'last month', value:'month'},
    {label:'last year', value:'year'}
  ];
  
  function customTheme(theme){
    return{
      ...theme,
      colors:{
        ...theme.colors,
        primary25:'#43425d',
        primary:'#3c4a64',
      },
    };
  }
  
  const chart = () => {
    let empSal = [];
    let empAge = [];
    axios.get("http://dummy.restapiexample.com/api/v1/employees")
    .then(res => {
      // console.log(res)
      for(const dataObj of res.data.data){
        empSal.push(parseInt(dataObj.employee_salary))
        empAge.push(parseInt(dataObj.employee_age))
      }
      const labels = empAge;
      
      
      const hour = {
        labels,
        datasets: [{
          label:'Agent performance',
          data: empSal,
          backgroundColor: getRandomColors(labels.length),
          borderWidth: 2
        }]
      }

      const day = {
        labels,
        datasets: [{
          label:'Agent performance',
          data: [3454,4555,4554,5454,4542,6543,3445,4567],
          backgroundColor: getRandomColors(labels.length),
          borderWidth: 2
        }]
      }

      switch (event) {
        case 'hour':
          setData = hour
          break;

        case 'day':
          setData = day
          break;

        default:
          break;
      }

      setChartData({
        setData
      })
    })
    .catch(err => {
      console.log(err);
    });
    
  }

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

  const handleChange = (value) => {
    event = value.value;
    console.log(event);
    // switch (event) {
    //   case 'hour':
    //     setData = hour
    //     break;

    //   case 'day':
    //     setData = day
    //     break;

    //   default:
    //     break;
    // }
  }

  return (
    <div className="card-one">
        <span className="dropdown-select">
          <Select options={options} defaultValue={options[0]} theme={customTheme} onChange={handleChange}/>
        </span>
        <Bar 
          data={chartData} 
          options={{
            responsive:true,
            scales:{
              yAxes:[{
                ticks:{
                  beginAtZero: true
                }
              }]
            },
            legend:{
              display: true,
              position: "bottom"
            }
          }}
          height={140}
        />
    </div>
  );
}

export default CanvasFour;
1
This question is a bit unclear and could be improved in a few ways. 1) Create a minimal, reproducible example that actually runs (i.e. add the MRE as a code snippet so that it can be run directly in the question); 2) Add context about what isn't working and what you have tried. All that being said, I'll take a stab at an answer: useState returns the current value (data in your case), and a function to change that data (setData). You're assigning directly to setData instead of calling it (e.g. setData(day)).benbotto
Hello! Thanks for your response. I make changes to the question. Please, will you take a look at it? I will appreciate it.Oluwatosin Daniel Owolabi
I have tried to make some edits to your question but its just not clear even after your update. but anyway, wait and see for folks to help you.Jay

1 Answers

1
votes

You should really put most of the function definitions outside of the render method because every time the component is rendered, all of the functions are recreated, which is unnecessary and can be easily avoided.

Anyway I refactored you code and now it looks like this.

const defaultDate = options[0];
const defaultData = {};

export default function App() {
  const [date, setDate] = React.useState(defaultDate.value);
  const [chartData, setChartData] = useState(defaultData);

  const handleChange = (value) => {
    const date = value.value;
    setDate(date);
  };

  React.useEffect(() => {
    getDataFromDate(date).then((chartData) => {
      setChartData(chartData);
    });
  }, [date]);

  return (
    <div className="card-one">
      <span className="dropdown-select">
        <Select
          options={options}
          onChange={handleChange}
        />
      </span>
      <Bar
        data={chartData}
        {...}
      />
    </div>
  );
}

While most of the functions and variables can be put outside of the function body like this.

const options = [
  { label: "last hour", value: "hour" },
  { label: "last day", value: "day" },
  { label: "last week", value: "week" },
  { label: "last month", value: "month" },
  { label: "last year", value: "year" }
];

const getRandomColors = (numOfBars) => {
  const letters = "0123456789ABCDEF".split("");
  let colors = [];
  for (let i = 0; i < numOfBars; i++) {
    let color = "#";
    for (let k = 0; k < 6; k++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    colors.push(color);
  }
  return colors;
};

function requestApi(date) {
  const labels = [9876, 4245, 2345, 3452, 6534];
  let result;

  switch (date) {
    case "hour":
      result = {
        labels,
        datasets: [
          {
            label: "Agent performance",
            data: [3428, 8743, 5748, 4675, 9265],
            backgroundColor: getRandomColors(labels.length),
            borderWidth: 2
          }
        ]
      };
      break;

    case "day":
      result = {
        labels,
        datasets: [
          {
            label: "Agent performance",
            data: [3454, 4555, 4554, 5454, 4542, 6543, 3445, 4567],
            backgroundColor: getRandomColors(labels.length),
            borderWidth: 2
          }
        ]
      };
      break;
    default:
      break;
  }
  return Promise.resolve(result);
}

function getDataFromDate(date) {
  return requestApi(date);
}

function customTheme(theme) {
  return {
    ...theme,
    colors: {
      ...theme.colors,
      primary25: "#43425d",
      primary: "#3c4a64"
    }
  };
}

Live Example

Edit 63925910/how-to-use-onchange-with-react-hook-on-react-select-to-change-data-base-on-user