代码之家  ›  专栏  ›  技术社区  ›  Yuriy Paraska

如何强制重新渲染react组件Chart(react Chart.js)并更新自定义插件?

  •  1
  • Yuriy Paraska  · 技术社区  · 1 年前

    我使用插件为所有点制作了工具提示,有深色和浅色两种背景色。但该插件只有在刷新页面后才能工作。我做了一个代码沙箱来显示一个问题。当你打开沙盒时,你会看到一个按钮切换。点击深色主题并刷新页面。

    import React, { useEffect, useState } from "react";
    import { Chart as ChartJS} from "chart.js";
    import { Line } from "react-chartjs-2";
    import faker from "faker";
    
    const labels = ["January", "February", "March", "April", "May", "June", "July"];
    
    export function App() {
      const [theme, setTheme] = useState(() => {
        const initialTheme = localStorage.getItem("theme");
        return initialTheme ? initialTheme : "light";
      });
    
      function getThemeFromLocalStorage() {
        const savedTheme = localStorage.getItem("theme");
        if (savedTheme) {
          setTheme(savedTheme);
        }
      }
    
      function toggleTheme() {
        setTheme((prevTheme) => {
          const newTheme = prevTheme === "light" ? "dark" : "light";
          localStorage.setItem("theme", newTheme);
          return newTheme;
        });
      }
    
      useEffect(() => {
        getThemeFromLocalStorage();
      }, [theme]);
    
      const allTooltips = theme?.startsWith("d") ? "#151429" : "#FFF";
    
      const data = {
        labels,
        datasets: [
          {
            fill: true,
            label: "Dataset 2",
            data: labels.map(() => faker.datatype.number({ min: 0, max: 1000 })),
            borderColor: "rgb(53, 162, 235)",
            backgroundColor: "rgba(53, 162, 235, 0.5)",
          },
        ],
      };
    
      const alwaysShowTooltip = {
        id: "alwaysShowTooltip",
        afterDatasetsDraw(chart) {
          const { ctx } = chart;
    
          ctx.save();
    
          chart.data.datasets.forEach((dataset, i: number) => {
            chart.getDatasetMeta(i).data.forEach((datapoint, index: number) => {
              const { x, y } = datapoint.tooltipPosition();
    
              const itemText = chart.data.datasets[i].data[index];
              const text = itemText !== null ? itemText + "%" : "";
    
              ctx.beginPath();
              ctx.fillStyle = itemText !== null ? allTooltips : "transparent";
              const textWidth = ctx.measureText(text).width;
              ctx.stroke();
    
              ctx.shadowOffsetX = 0;
              ctx.shadowOffsetY = 5;
              ctx.shadowBlur = 5;
              ctx.shadowColor = "rgba(0, 0, 0, 0.15)";
              ctx.roundRect(
                x - (textWidth + 10) / 2,
                y - 25,
                textWidth + 10,
                16,
                4,
              );
              ctx.fill();
              ctx.shadowColor = "transparent";
    
              //text
              ctx.font = "Regular 10px Poppins";
              ctx.fillStyle = "gray";
              ctx.fillText(text, x - textWidth / 2, y - 14);
            });
          });
        },
      };
    
      return (
        <>
          <Line options={options} data={data} plugins={[alwaysShowTooltip]} />
          <button onClick={toggleTheme}>Toggle Theme: {theme}</button>
        </>
      );
    }
    

    CodeSandbox

    我尝试了一些想法并寻找决定,但没有找到。

    1 回复  |  直到 1 年前
        1
  •  1
  •   Drew Reese    1 年前

    一个非常琐碎的解决方案是在 Line theme 状态更新。

    使用的示例 主题 状态值 关键:

    <Line
      key={theme} // <--
      options={options}
      data={data}
      plugins={[alwaysShowTooltip]}
    />
    

    这里的想法是 线 组件将重新安装并使用计算的电流 data options 用于渲染图表。

    推荐文章