How to use onChange with react hook on react select to change data base on user select

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;

Upvotes: 3

Views: 9011

Answers (1)

NearHuscarl
NearHuscarl

Reputation: 81823

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

Upvotes: 2

Related Questions