Ant design Chart onReady函数使用外部变量问题

news/2024/7/15 17:41:35 标签: react.js, react, javascript, 前端

一、问题描述

封装了一个Chart组件,它接收一个boolean类型的props,根据这个boolean的true或false执行不同的操作。经过console.log验证,onReady函数只会在组件初次渲染时取到props值,不管后面的props变化成什么都无法重新取值。

二、代码描述

初始化状态为0,useRequest拿到后端的值为1。

传递给Chart组件的props,是可以拿到最新的,可以在40行的打印中看到。

但是onReady挂载的坐标轴点击事件打印出的却不会变化,依然是0。

javascript">javascript">// 父组件
import React, { useState, useEffect } from 'react';
import { useRequest } from 'ahooks';

const FatherComponent = () => {
    const [flag, setFlag] = useState(0);

    const { data, loding, run } = useRequest(
        async (params) => {
            try {
                const { data, success, msg } = awiat getData();
                if (!success) {
                    return [];
                }
                setFlag(data.flag)
                return data;
            } catch(e) { console.log(e) };
            return [];
        }, { manual: true })

    useEffect(() => {
        if (!isUndefined(data)) {
            setFlag(data.flag)
        }
    }, [data])

    return (
        <div>
            {data && <ChildChartComponent data={data} flag={flag} />}
        </div>
    )
}
export default FatherComponent;



// 子组件
import React from 'react'
import { Column } from "@ant-design/plots";

const ChildChartComponent = (props) => {
    const { data, flag } = props;
    console.log(flag)
    const config = {
        data,
        // ...many config settings, it's unimportant
        onReady: (plot) => {
            plot.on("axis-label:click", (e) => {
                if (Number(flag) === 1) {
                    console.log('执行props.flag为true的逻辑');
                } else {
                    console.log('执行props.flag为false的逻辑');
                }
            })
        }
    }
    
    return (
        <Column {...config} />
    )
}
export default ChildChartComponent;

三、原因解析

这个问题研究了整整一天,换了很多种方式都寻找不到问题所在。

一开始想是我得状态不对,再之后是觉得是最新的onReady没有被重新赋值给chart组件。

在官方文档中没找到相关问题描述,于是乎,我打开Github进入到组件仓库,在issues里找Bug和提问,终于被我找到跟我有相关问题的同志。

原来是因为onReady()函数是一个闭包,在子组件初次渲染的时候,它保存的值是初始值0,所以一直拿不到新状态。

四、修改子组件的写法,利用useRef解决闭包问题

我们声明一个ref,在effect中的deps校验规则设置为flag,effect方法内将ref的current每一次都指向flag。

将onReady中的on方法内的通过flag判断改为通过flagRef.current判断即可。

useRef可以解决闭包问题的原因在于: useRef 返回的是 { current: null },将对应数据赋值给 current,在声明之后,引用地址是不变的。

javascript">javascript">// 子组件
import React, { useRef, useEffect } from 'react'
import { Column } from "@ant-design/plots";

const ChildChartComponent = (props) => {
    const { data, flag } = props;
    const flagRef = useRef(null)
    useEffect(() => {
        flagRef.current = flag;
    }, [flag])

    const config = {
        data,
        // ...many config settings, it's unimportant
        onReady: (plot) => {
            plot.on("axis-label:click", (e) => {
                if (Number(flagRef.current) === 1) {
                    console.log('执行props.flag为true的逻辑');
                } else {
                    console.log('执行props.flag为false的逻辑');
                }
            })
        }
    }
    
    return (
        <Column {...config} />
    )
}
export default ChildChartComponent;


http://www.niftyadmin.cn/n/116760.html

相关文章

java25种设计模式之工厂模式

Java设计模式 - 工厂模式 工厂模式是一种创建模式&#xff0c;因为此模式提供了更好的方法来创建对象。 在工厂模式中&#xff0c;我们创建对象而不将创建逻辑暴露给客户端。 例子 在以下部分中&#xff0c;我们将展示如何使用工厂模式创建对象。 由工厂模式创建的对象将是…

链表经典刷题--快慢指针与双指针

本篇总结链表解题思路----快慢指针&#xff0c;其实也就是双指针&#xff0c;这个快慢并不单纯指“快慢”&#xff0c;它更多的可以表示&#xff0c;速度快慢&#xff0c;距离长度&#xff0c;时间大小等等&#xff0c;用法很有趣也很独特&#xff0c;理解它的思想&#xff0c;…

WebRTC新增FFmpeg视频编解码模块

1、整体描述目前webrtc内置的视频编解码器包括&#xff1a;VP8、VP9、AV1和H264。一般情况下载pc端基本可以满足大部分的需求&#xff0c;但是有时候为了进行编解码器的扩展包括支持H265或者是支持硬件编解码以提升效率时需要新增编解码模块。2、新增外部编码器编码器实现的要点…

【LeetCode】剑指 Offer(14)

目录 题目&#xff1a;剑指 Offer 32 - I. 从上到下打印二叉树 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 题目&#xff1a;剑指 Offer 32…

锚点定位使内容在指定区域显示

1、问题描述 在使用锚点定位时&#xff0c;使用 scrollIntoView 方法&#xff0c;导致整个页面随着锚点跳转 2、问题分析 因为最开始做需求的时候&#xff0c;只在最外层设置了一个滚动条&#xff0c;所以导致整体锚点的跳转是随着最外层滚动条距离顶部的高度跳转的&#xf…

【NLP相关】Transformer模型:从Seq2Seq到自注意力机制(Transformer原理、公式推导和案例)

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Nacos 2.2.0支持postgresql数据库

github地址&#xff1a;个人仓库本文基于扩展源码的方式进行的集成&#xff0c;官方推荐的方式为&#xff1a;扩展插件包源码修改1.1根pom增加postgresql依赖<postgresql.version>42.5.1</postgresql.version><dependency><groupId>org.postgresql<…

python魔术方法

魔术方法 魔术方法就是一个类中的方法&#xff0c;和普通方法唯一的不同是普通方法需要调用&#xff0c;而魔术方法是在特定时刻自动触发。这些魔术方法的名字特定&#xff0c;不能更改&#xff0c;但是入口参数的名字可以自己命名。 基本魔术方法 new(cls[,…]) _new_ 是在…