我知道当一个按钮被点击时如何从子组件发送数据到父组件,但该按钮应该在子组件中. 我想要的是,当一个按钮被点击,但该按钮在父组件而不是子组件中时,如何从子组件发送数据到父组件.

例如,我有这样的东西:

父零部件

function ParentComponent() {
  const handleChildData = (childData) => {
    console.log(childData);
  }
  return (
    <> 
    <ChildComponent onDataGet={handleChildData} />
    <div>ParentComponent</div>
    </>
  )
}

子组件

function ChildComponent({onDataGet}) {
  const data = {
    firstName: "John",
    lastName: "Smith",
  }

  // Based on something, execute this function:
  onDataGet(data)

  return (
    <div>ChildComponent</div>
  )
}

I have tried this approach:

定义了一个状态,在每次点击时状态加一,也将这个状态传递给子组件,在那里只要状态发生变化,子组件中的useEffect就会发生,并执行onDataGet函数.就像这样:

父零部件

function ParentComponent() {
  const [isTrigerred, setIsTrigerred] = useState(1);
  const handleChildData = (childData) => {
    console.log(childData);
  };
  return (
    <>
      <ChildComponent onDataGet={handleChildData} gotChanged={isTrigerred} />
      <div>ParentComponent</div>
      <Button variant="contained" onClick={() => setIsTrigerred((prev) => prev + 1)}>
        Click Me
      </Button>
    </>
  );
}

子组件

function ChildComponent({ onDataGet, gotChanged}) {
  const data = {
    firstName: "John",
    lastName: "Smith",
  };

  useEffect(() => {
    // Don't execute in first render
    if (gotChanged !== 1) {
      onDataGet(data);
    }
  }, [gotChanged]);

  return <div>ChildComponent</div>;
}

但我正在寻找更好的方法,如果有的话.

谢谢.

推荐答案

利用ref的缓存功能,可以实现父组件调用子组件的方法.

import {useRef} from 'react'

function ParentComponent() {
  const actionRef = useRef();
  return (
    <>
      <ChildComponent ref={actionRef} />
      <div>ParentComponent</div>
      <Button
        variant="contained"
        onClick={() => {
          const childData = actionRef.current.getData();
          console.log('childData...', childData);
        }}
      >
        Click Me
      </Button>
    </>
  );
}
import {forwardRef} from 'react'

const ChildComponent = forwardRef(function (props, ref) {
  const data = {
    firstName: 'John',
    lastName: 'Smith',
  };

  useImperativeHandle(
    ref,
    () => {
     // the return object will pass to parent ref.current, so you can add anything what you want.
      return {
        getData: () => data,
      }
    },
    [data],
  );

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

Reactjs相关问答推荐

MUImaterial -ui-如何将文本字段和 Select 分组?

Inbox Enum类型以React组件状态时出现TypScript错误

如何使用react-router-dom导航到网页中的其他路由?

为什么这个'Suspense'子组件在挂起promise解决后会丢失它的状态,而不是呈现?<>

ReferenceError:未在Redux组件中定义窗口

Redux Provider Stuck甚至彻底遵循了文档

有没有办法让两个状态在两次精准渲染中更新?

为多租户SSO登录配置Azure AD应用程序

如何访问子集合中的文档?

为什么查询错误在处理后仍出现在控制台中?RTK查询+ React

React Router:在没有手动页面刷新的情况下,路由不会更新内容

StrictMode+SetInterval=双重渲染(即使使用useEffect清理)

useEffect 内的 onClick 和 addEventListener 之间的 click 事件顺序差异

React - 添加了输入数据但不显示

使用带有搜索字符串的全局过滤器时如何在 React-Table 中进行精确匹配?

MUI - ButtonGroup fullWidth 条件屏幕大小不起作用?

如何通过onpress on view in react native flatlist来降低和增加特定视图的高度?

react 事件顺序

将 C# Razor 条件块转换为 React.js 代码

material uireact ,如何从表格中删除阴影?试图找到 api 但找不到正确的属性