首页 > 解决方案 > 在附加了 setstate 完整代码 Reactjs 更新后,我的 Chartjs 没有更新

问题描述

Chartjs 在更新数据集值后没有显示我的更改。我有来自材料 ui 的滑块控制器。我正在使用'immutability-helper'的导入更新;更新状态。

<PrettoSlider valueLabelDisplay="auto" aria-label="pretto slider" defaultValue={20} onChange={handleChange}/>

我的图表看起来像这样。

const RadarChart = () => {
const data = {
  datasets: [
    {
      data: [1, 3, 7, 3, 4, 6],
    },
  ],
};
  const [update, setUpdate] = useState(data.datasets[0].data[2]);
  // Initialized a hook to hold the reference to the title div.
  const titleRef = useRef();

  const handleChange = (e, v) => {
    // Imutable Update .. nested Object .. really hard to this manually. 
    const newDate = update(dataState,{
      datasets: {
        data: {$set: v}
      }
    } )
    setDataState(newDate)
    titleRef.current.render();
    titleRef.current.update();
  };

  return (
    <>
      <CustomizedSlider handleChange={handleChange} />
      <Radar ref={titleRef} data={data} />
    </>
  );
};

滑块工作,我在我的 handleChange 方法中得到了正确的值,所以我的问题依赖于更新图表本身的状态。

标签: javascriptreactjschart.js

解决方案


在 ReactJS 中,您需要对要更新的任何数据(状态)使用useState()钩子。像这样的东西:

  const RadarChart = () => {
  const data = {
    datasets: [
      {
        data: [1, 3, 7, 3, 4, 6],
      },
    ],
  }
  const [dataState, setDataState] = useState(data)
  const [update, setUpdate] = useState(data.datasets[0].data[2]);    // <-- Is this necessary? You don't seem to be using it.
  
  const titleRef = useRef();

  const handleChange = (e, v) => {
      // create a copy of the array:
      let newArr = [...dataState.datasets[0].data];
      newArr[2] = v;
      // set state to updated array:
      setDataState(previous => ({
          ...previous,
          datasets: [{data: newArr}]
      }))
      setUpdate(v);     // best to use v here as dataState may not be finished updating, but again, don't know if necessary.
  };

  useEffect(()=>{
    if (titleRef.current) {  
      titleRef.current.render()
      titleRef.current.update()
    }
  }, [dataState])    // moved this update into a `React.useEffect` block, to make sure `dataState` has updated when they are triggered.

  return (
    <>
      <CustomizedSlider handleChange={handleChange} />
      <Radar ref={titleRef} data={dataState} />
    </>
  );
};
 

您可以做的另一件事是对数组的一个元素使用状态,这样可以节省几行代码,因为状态是整数而不是对象。你会这样做:

  const RadarChart = () => {
  const [variableState, setVariableState] = useState(7);
  const data = {
    datasets: [
      {
        data: [1, 3, variableState, 3, 4, 6]
      },
    ],
  };
  
  const titleRef = useRef();

  const handleChange = (e, v) => {
      setVariableState(v);
  };

  useEffect(()=>{
    if (titleRef.current) {  
      titleRef.current.render()
      titleRef.current.update()
    }
  }, [variableState])

  return (
    <>
      <CustomizedSlider handleChange={handleChange} />
      <Radar ref={titleRef} data={data} />
    </>
  );
};

不过,这可能会更棘手,具体取决于您获取数据的方式。

更新有关不变性助手的问题

乍一看,immutability-helper 的问题,看起来你正试图将数组本身的值设置为vv只是一个数字)。您应该在更新方法中使用data而不是。dataState此外,它看起来像是您正在创建的不同对象。data.datasets之前是一个数组,它是您更新中的一个对象。不完全确定您为什么不setDataState以与上述相同的方式使用该函数,似乎不那么复杂,并且不需要外部库。

我实际上只是自己阅读了文档,但您可以尝试类似于上面的内容:

let newArr = [...data.datasets[0].data];
newArr[2] = v;
const newData = update(data,{
      datasets: {$set: [{data: newArr}]}});
setDataState(newData);

推荐阅读