You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React中从一个子组件调用另一个子组件函数的问题及报错解决

子组件间调用函数的问题

我现在有一个父组件和两个子组件,点击第一个子组件的按钮时,想调用第二个子组件里的函数。我懂一点forwardRef和父组件调用子组件函数的方法,但不知道子组件之间怎么实现这种调用。搜了相关文档,只找到父对子、子对父的案例,没找到子组件间的调用方案。

当前报错:

props.onZoomHandler is not a function


现有代码

父组件

import Child1 from './child1';
import Child2 from './child2';

const parent = () => {
    const childRef = useRef();

    return (
        <Child1 onZoomHandler={childRef.current?.zoomHandler} />
        <Child2 ref={childRef} />
    )
}

export default parent;

Child1组件

const child1 = (props) => {
    const zoomHandler = () => {
        props.onZoomHandler();
    }
    return (
        <Button onClick={zoomHandler} />
    )
}

export default child1;

Child2组件

import { forwardRef, useImperativeHandle } from 'react';    

const child2 = forwardRef((props, ref) => {
    useImperativeHandle(ref, () => ({
        zoomHandler
    }));

    const zoomHandler =() => {

    }

    return (
        <div ref={ref} />
    )
}

export default child2;

问题原因与修正方案

核心问题

  1. 父组件初始化时childRef.current为null,直接传递childRef.current?.zoomHandler给Child1,此时这个值是undefined,并非函数,点击时触发报错
  2. Child2中zoomHandler定义在useImperativeHandle之后,存在变量提升问题,导致useImperativeHandle无法获取正确的函数引用

修正后的代码

父组件(关键调整:传递回调函数而非直接传ref属性)

import Child1 from './child1';
import Child2 from './child2';
import { useRef } from 'react'; // 补充导入useRef

// 组件名首字母大写是React规范
const Parent = () => {
    const childRef = useRef();

    // 封装回调,确保调用时能拿到最新的ref.current
    const triggerChild2Zoom = () => {
        childRef.current?.zoomHandler();
    };

    return (
        <> {/* 必须用Fragment包裹多个子元素 */}
            <Child1 onZoomHandler={triggerChild2Zoom} />
            <Child2 ref={childRef} />
        </>
    );
};

export default Parent;

Child2组件(关键调整:调整函数定义顺序)

import { forwardRef, useImperativeHandle } from 'react';    

const Child2 = forwardRef((props, ref) => {
    // 先定义函数,再传给useImperativeHandle
    const zoomHandler = () => {
        console.log("Child2的zoomHandler已执行");
        // 在这里编写你的业务逻辑
    };

    useImperativeHandle(ref, () => ({
        zoomHandler
    }));

    // 无需将ref挂在DOM元素上,useImperativeHandle已对外暴露方法
    return <div />;
});

export default Child2;

Child1组件(规范组件名)

const Child1 = (props) => {
    const zoomHandler = () => {
        props.onZoomHandler();
    };
    return <button onClick={zoomHandler}>触发Child2缩放</button>;
};

export default Child1;

补充说明

React遵循单向数据流规则,子组件之间无法直接通信,必须通过父组件作为中间层传递逻辑。你原本的思路是正确的:用forwardRef+useImperativeHandle让父组件拿到子组件的方法,再通过props把触发逻辑传给另一个子组件,只是初始化时机和变量顺序没处理到位。

内容的提问来源于stack exchange,提问作者udarts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:57:49