ant-design-charts icon indicating copy to clipboard operation
ant-design-charts copied to clipboard

🧐[问题]存不存在不用onReady能绑定事件得方法?

Open zjian233 opened this issue 2 years ago • 1 comments

🧐 问题描述

目前已知的绑定事件的方法是在onReady函数上绑定g2plot的事件,例如:

    <DemoPie
        data={data}
        onReady={(plot) => {
          // 这里绑定事件
          plot.on("element:click", () => {
            console.log(666);
          });
        }}
      />

但是这样写有个问题,因为onReady是在子组件第一次渲染的时候执行的,导致里面的事件处理函数的作用域其实是那次渲染的闭包 比如:

import React, { memo, useState } from "react";
import { Pie } from "@ant-design/charts";
import { isEqual } from "lodash-es";

const DemoPie: React.FC<any> = memo(
  ({ data, onReady }) => {
    var config = {
      data,
      angleField: "value",
      colorField: "type",
      radius: 0.8,
      label: { type: "outer" },
      interactions: [{ type: "element-active" }],
      onReady
    };
    return <Pie {...config} />;
  },
  (pre, next) => {
    return isEqual(pre?.data, next?.data);
  }
);

const Demo: React.FC = () => {
  const [data, setData] = useState([
    {
      type: "分类一",
      value: 27
    },
    {
      type: "分类二",
      value: 25
    }
  ]);

  return (
    <div>
      <button
        onClick={() => {
          setData([{ type: "1", value: 10 }]);
        }}
      >
        修改data
      </button>
      <DemoPie
        data={data}
        onReady={(plot) => {
          plot.on("element:click", () => {
            console.log(data);
          });
        }}
      />
    </div>
  );
};

第一次点击元素,打印的是一开始的data没问题,然后点击按钮修改data之后点击元素,打印的data还是闭包的值。

然后我的处理方法是在前面加上data的ref, 每次渲染的时候都重新赋值, 打印的时候打印最新的ref的值

const Demo: React.FC = () => {
  const [data, setData] = useState([
    {
      type: "分类一",
      value: 27
    },
    {
      type: "分类二",
      value: 25
    }
  ]);
  const dataRef = useRef(null);
  dataRef.current = data;

  return (
    <div>
      <button
        onClick={() => {
          setData([{ type: "1", value: 10 }]);
        }}
      >
        修改data
      </button>
      <DemoPie
        data={data}
        onReady={(plot) => {
          plot.on("element:click", () => {
            console.log(dataRef.current);
          });
        }}
      />
    </div>
  );
};
  1. 想问下有没有其他更好的实现方法。
  2. 有没有提供其他api,比如直接给元素绑定事件? 这样就不会有这个问题了。(感谢)

zjian233 avatar Aug 27 '22 08:08 zjian233

非常好的一个问题,应该有不少同学遇到过,目前没有更好的解决办法。

lxfu1 avatar Aug 30 '22 03:08 lxfu1

https://juejin.cn/post/7196652592372662331#heading-2

lxfu1 avatar Feb 14 '23 07:02 lxfu1

厉害了,解决了

stoiCasey avatar Mar 03 '23 04:03 stoiCasey