3

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;
3
  • 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)). Commented Sep 16, 2020 at 18:41
  • Hello! Thanks for your response. I make changes to the question. Please, will you take a look at it? I will appreciate it. Commented Sep 17, 2020 at 10:05
  • 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. Commented Sep 17, 2020 at 13:27

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

3 Comments

@OluwatosinDanielOwolabi you should put your async code in React.useEffect. I've updated the example, replace requestApi() definition with your code that use axios to request data.
Thanks for your swift response! Your solution works fine, but the moment I add API, it stops working. I'm using Axios to get data from an API. I used Axios inside function getDataFromDate(date) just before const labels. Can you please check the attached code in my initial question here, not codesandbox.
There are multiple errors in your second link in the question. I've fixed all of them in my code sample. Please read my code carefully and ask me anything in the chat if you don't understand any parts of it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.