【问题标题】:How to use onChange with react hook on react select to change data base on user select如何在反应选择上使用 onChange 和反应钩子来根据用户选择更改数据库
【发布时间】:2021-01-03 15:09:09
【问题描述】:

我正在尝试在 React Hooks 中使用 useState 更改 React-Select 值时更改 Chart.js 数据集。

在handleChange函数中的console.log(event),我得到了想要的结果,但是在下面写的switch语句中使用它是个问题。

参考代码在这里 - https://codesandbox.io/s/sparkling-morning-8lghs?file=/src/App.js:925-979

在 React-Select 添加 onChange 后,尝试实现更改图表数据集的逻辑:https://codesandbox.io/s/hopeful-fog-55yv8?file=/src/App.js

如何在 switch 语句的 handleChange 函数中使用我得到的值?

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) 创建一个实际运行的最小的、可重现的示例(即将 MRE 添加为代码 sn-p 以便它可以直接在问题中运行); 2)添加有关哪些内容不起作用以及您尝试过的内容的上下文。话虽如此,我将尝试回答:useState 返回当前值(在您的情况下为data),以及更改该数据的函数(setData)。您直接分配给setData,而不是调用它(例如setData(day))。
  • 您好!感谢您的答复。我对问题进行了更改。请问,你会看一下吗?我会很感激的。
  • 我已尝试对您的问题进行一些修改,但即使在您更新后仍不清楚。不过不管怎样,等着看人帮你吧。

标签: javascript reactjs react-select


【解决方案1】:

你真的应该把大部分函数定义放在 render 方法之外,因为每次渲染组件时,都会重新创建所有函数,这是不必要的,很容易避免。

反正我重构了你的代码,现在看起来像这样。

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>
  );
}

虽然大多数函数和变量都可以像这样放在函数体之外。

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"
    }
  };
}

现场示例

【讨论】:

  • @OluwatosinDanielOwolabi 你应该把你的异步代码放在React.useEffect。我已经更新了示例,将 requestApi() 定义替换为您使用 axios 请求数据的代码。
  • 感谢您的快速回复!您的解决方案工作正常,但我添加 API 的那一刻,它停止工作。我正在使用 Axios 从 API 获取数据。我在 const 标签之前在函数 getDataFromDate(date) 中使用了 Axios。您能否在此处检查我最初问题中的附加代码,而不是代码框。
  • 问题的第二个链接中有多个错误。我已经在我的代码示例中修复了所有这些问题。请仔细阅读我的代码,如果您不理解其中的任何部分,请在chat 中向我提问。
猜你喜欢
  • 1970-01-01
  • 2019-05-25
  • 2018-07-31
  • 2022-01-02
  • 2021-06-09
  • 1970-01-01
  • 2021-01-16
  • 1970-01-01
  • 2020-10-15
相关资源
最近更新 更多