reactjs 当在react中点击父节点中的按钮时,如何将数据从子节点发送到父节点?

2o7dmzc5  于 2023-05-17  发布在  React
关注(0)|答案(2)|浏览(133)

我知道当一个按钮被点击时如何从子组件向父组件发送数据,但是按钮应该在子组件中。我想要的是,当一个按钮被点击时,如何将数据从子组件发送到父组件,但是按钮在父组件中而不是在子组件中。
例如,我有这样的东西:
父组件

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>
  )
}

我尝试过这种方法:

定义了一个状态,每次点击状态递增1,也把这个状态传递给child,在那里,只要状态改变,child组件中的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>;
}

但我在寻找更好的方法,如果有的话。
谢谢

vwhgwdsa

vwhgwdsa1#

一种方法是在子组件中传递一个setter函数,如下所示:
父组件:

function ParentComponent() {
  const [getChildData, setGetChildData] = useState(() => null);

  const handleChildData = (childData) => {
    const childData = getChildData();
    // etc...
  };
  return (
    <>
      <ChildComponent getDataSetter={setGetChildData} />
      <div>ParentComponent</div>
      <Button variant="contained" onClick={handleChildData}>
        Click Me
      </Button>
    </>
  );
}

子组件:

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

  useEffect(() => {
    // Only way to use a state for a function, because the setter function
    // can take a callback to set the new value
    getDataSetter(() => () => data);
  }, [data]);

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

dldeef672#

ref的缓存功能可用于实现父组件调用子组件的方法。

import {useRef} from 'react'

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

forwardRef(function ChildComponent(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>;
});

相关问题