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

React.js中如何实现子组件间传值及跨组件方法调用

React 跨组件交互解决方案(针对你的组件结构)

首先修正你提供的Parent组件语法错误:JSX组件名不能包含空格,需改为<Child1 />、<Child2 />格式,以下是修正后的基础代码:

import './css/style.css';
import Child1 from './Child1';
import Child2 from './Child2';
import Child3 from './Child3';

const Parent = () => {
  return (
    <div>
      <Child1 />
      <Child2 />
      <Child3 />
    </div>
  );
};
export default Parent;

需求1:Child1的onClick事件调用Child2的方法

通过父组件作为中间层,结合forwardRef和useImperativeHandle暴露Child2的方法给父组件,再将调用逻辑传递给Child1。

代码实现

Child2组件

import { useImperativeHandle, forwardRef } from 'react';

const Child2 = forwardRef((props, ref) => {
  // 定义要被调用的方法
  const child2Method = () => {
    console.log('Child2的方法被触发');
    // 此处编写方法的具体逻辑
  };

  // 向父组件暴露指定方法
  useImperativeHandle(ref, () => ({
    child2Method
  }));

  return <div>Child2</div>;
});

export default Child2;

Parent组件

import { useRef } from 'react';
import Child1 from './Child1';
import Child2 from './Child2';
import Child3 from './Child3';
import './css/style.css';

const Parent = () => {
  const child2Ref = useRef(null);

  // 封装调用Child2方法的逻辑
  const triggerChild2Method = () => {
    child2Ref.current?.child2Method();
  };

  return (
    <div>
      <Child1 onClick={triggerChild2Method} />
      <Child2 ref={child2Ref} />
      <Child3 />
    </div>
  );
};

export default Parent;

Child1组件

const Child1 = ({ onClick }) => {
  return <button onClick={onClick}>点击调用Child2方法</button>;
};

export default Child1;

需求2:Child1的数据传递给Parent组件

通过父组件传递回调函数给Child1,Child1在需要传数据时调用该函数,将数据作为参数传入。

代码实现

Child1组件

import { useState } from 'react';

const Child1 = ({ onClick, onSendDataToParent }) => {
  const [child1Data, setChild1Data] = useState('Child1的待传数据');

  const handleSendData = () => {
    // 调用父组件传来的回调,传递数据
    onSendDataToParent(child1Data);
  };

  return (
    <div>
      <button onClick={onClick}>调用Child2方法</button>
      <button onClick={handleSendData}>向Parent传数据</button>
    </div>
  );
};

export default Child1;

Parent组件

import { useRef, useState } from 'react';
import Child1 from './Child1';
import Child2 from './Child2';
import Child3 from './Child3';
import './css/style.css';

const Parent = () => {
  const child2Ref = useRef(null);
  const [receivedData, setReceivedData] = useState('');

  const triggerChild2Method = () => {
    child2Ref.current?.child2Method();
  };

  // 接收Child1传来的数据
  const handleChild1Data = (data) => {
    setReceivedData(data);
    console.log('Parent收到数据:', data);
  };

  return (
    <div>
      <Child1 onClick={triggerChild2Method} onSendDataToParent={handleChild1Data} />
      <Child2 ref={child2Ref} />
      <Child3 />
      {receivedData && <p>Parent接收的数据:{receivedData}</p>}
    </div>
  );
};

export default Parent;

需求3:Child1向Child2传递数据的可行方案及最佳实践

方案1:父组件中转(推荐的最佳实践)

利用父组件的状态作为数据中转,Child1将数据传给父组件,父组件再通过props将数据传递给Child2,完全符合React单向数据流原则。

代码实现

Parent组件

import { useRef, useState } from 'react';
import Child1 from './Child1';
import Child2 from './Child2';
import Child3 from './Child3';
import './css/style.css';

const Parent = () => {
  const child2Ref = useRef(null);
  const [sharedData, setSharedData] = useState('');

  const triggerChild2Method = () => {
    child2Ref.current?.child2Method();
  };

  const handleChild1Data = (data) => {
    setSharedData(data); // 更新父组件状态,中转数据
  };

  return (
    <div>
      <Child1 onClick={triggerChild2Method} onSendDataToParent={handleChild1Data} />
      <Child2 ref={child2Ref} receivedData={sharedData} />
      <Child3 />
    </div>
  );
};

export default Parent;

Child2组件

import { useImperativeHandle, forwardRef, useEffect } from 'react';

const Child2 = forwardRef(({ receivedData }, ref) => {
  const child2Method = () => {
    console.log('Child2的方法被触发');
  };

  // 监听来自Child1的数据变化
  useEffect(() => {
    if (receivedData) {
      console.log('Child2收到数据:', receivedData);
      // 此处编写数据接收后的逻辑
    }
  }, [receivedData]);

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

  return (
    <div>
      Child2
      {receivedData && <p>接收自Child1的数据:{receivedData}</p>}
    </div>
  );
});

export default Child2;

方案2:Context API(适合多组件共享数据场景)

如果项目中有多个组件需要共享同类数据,或组件层级较深,可使用Context API统一管理数据,避免多层props传递的繁琐。

代码实现

1. 创建Context
import { createContext, useContext, useState } from 'react';

const SharedDataContext = createContext();

export const SharedDataProvider = ({ children }) => {
  const [sharedData, setSharedData] = useState('');

  return (
    <SharedDataContext.Provider value={{ sharedData, setSharedData }}>
      {children}
    </SharedDataContext.Provider>
  );
};

export const useSharedData = () => useContext(SharedDataContext);
2. 包裹上层组件(如App.js)
import { SharedDataProvider } from './SharedDataContext';
import Parent from './Parent';

function App() {
  return (
    <SharedDataProvider>
      <Parent />
    </SharedDataProvider>
  );
}

export default App;
3. 修改Child1组件
import { useState } from 'react';
import { useSharedData } from './SharedDataContext';

const Child1 = ({ onClick }) => {
  const { setSharedData } = useSharedData();
  const [child1Data, setChild1Data] = useState('Child1通过Context传递的数据');

  const handleSendData = () => {
    setSharedData(child1Data);
  };

  return (
    <div>
      <button onClick={onClick}>调用Child2方法</button>
      <button onClick={handleSendData}>通过Context传数据</button>
    </div>
  );
};

export default Child1;
4. 修改Child2组件
import { useImperativeHandle, forwardRef, useEffect } from 'react';
import { useSharedData } from './SharedDataContext';

const Child2 = forwardRef((props, ref) => {
  const { sharedData } = useSharedData();
  const child2Method = () => {
    console.log('Child2的方法被触发');
  };

  useEffect(() => {
    if (sharedData) {
      console.log('Child2通过Context收到数据:', sharedData);
    }
  }, [sharedData]);

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

  return (
    <div>
      Child2
      {sharedData && <p>Context接收的数据:{sharedData}</p>}
    </div>
  );
});

export default Child2;

方案3:自定义事件(不推荐)

通过浏览器自定义事件实现数据传递,但这种方式脱离React数据流,难以追踪数据变化,容易引发调试和维护问题,仅在特殊场景下考虑使用。

代码示例(Child1)

const Child1 = ({ onClick }) => {
  const handleSendData = () => {
    const event = new CustomEvent('child1Data', { detail: 'Child1的自定义事件数据' });
    window.dispatchEvent(event);
  };

  return (
    <div>
      <button onClick={onClick}>调用Child2方法</button>
      <button onClick={handleSendData}>通过自定义事件传数据</button>
    </div>
  );
};

export default Child1;

代码示例(Child2)

import { useImperativeHandle, forwardRef, useEffect } from 'react';

const Child2 = forwardRef((props, ref) => {
  const child2Method = () => {
    console.log('Child2的方法被触发');
  };

  useEffect(() => {
    const handleData = (e) => {
      console.log('Child2通过自定义事件收到数据:', e.detail);
    };
    window.addEventListener('child1Data', handleData);
    // 组件卸载时移除监听
    return () => window.removeEventListener('child1Data', handleData);
  }, []);

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

  return <div>Child2</div>;
});

export default Child2;

最佳实践总结

  1. 同级组件通信优先使用父组件中转,符合React单向数据流,逻辑清晰易维护。
  2. 多组件/跨层级共享数据时,使用Context API,减少props传递的冗余代码。
  3. 避免使用自定义事件或全局变量,这类方式会破坏React数据流机制,增加维护成本。
  4. 调用同级组件方法时,采用forwardRef+useImperativeHandle组合,明确暴露组件可调用方法,避免直接操作组件实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:45:13