如何使用react调用父事件的子方法?

Ark*_*lys 8 reactjs react-redux

我有一个子组件需要监听其父组件之一event。更准确地说,我在子组件中有一个函数,它event从父组件中获取参数 an 。我想每次event发生时都调用这个函数。

作为示例,下面是一个代码片段:

class Parent extends React.Component {
  handleKeyDown = (event) => {
    // Call the child function doSomething()
  }

  render() {
    return (
      <input
        type="text"
        onKeyDown={this.handleKeyDown}
      >

      <Child />
    )
  }
}
Run Code Online (Sandbox Code Playgroud)
class Child extends React.Component {
  doSomething = (event) => {
    // Get the event from parent
  }

  render() {
    return (
      ...
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

我考虑过两种方法:

  • 用于ref从父函数调用子函数onKeyDown
  • 使用 astate存储事件并将其作为 a 传递props给子级,然后使用 监听props更改getDerivedStateFromProps

然而,这些解决方案似乎都不是很有吸引力。我也考虑过使用 redux 函数,但我需要来自子组件以及event父组件的数据...我想知道是否有一种干净的方法可以做到这一点?

Ark*_*lys 12

更新(挂钩):

我更新了我的组件以使用钩子,并最终使用useRef()useImperativeHandle()forwardRef()来处理这种情况:

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

  const handleKeyDown = (event) => {
    // Call the child function doSomething()
    childRef.current.doSomething(event);
  };
   
  return (
    <input
      type="text"
      onKeyDown={handleKeyDown}
    >
    
    <Child ref={childRef} />
  );
};
Run Code Online (Sandbox Code Playgroud)
const Child = forwardRef((props, ref) => {
  useImperativeHandle(ref, () => ({
    doSomething: (event) => {
      // Get the event from parent
    }
  }));

  return (
    [...]
  );
});
Run Code Online (Sandbox Code Playgroud)

原始答案(类组件):

我决定使用Francis Malloch这篇文章1中提供的解决方案:

class Parent extends React.Component {
  childCallables = null;
    
  setChildCallables = (callables) => {
    this.childCallables = callables;
  }
    
  handleKeyDown = (event) => {
    // Call the child function doSomething()
    this.childCallables.doSomething(event);
  }
    
  render() {
    return (
      <input
        type="text"
        onKeyDown={this.handleKeyDown}
      >
    
      <Child setCallables={this.setChildCallables} />
    )
  }
}
Run Code Online (Sandbox Code Playgroud)
class Child extends React.Component {
  componentDidMount() {
    this.props.setCallables({
      doSomething: this.doSomething
    });
  }
    
  doSomething = (event) => {
    // Get the event from parent
  }
    
  render() {
    return (
      [...]
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

基本上,我使用道具来存储我需要从父级访问的子级方法。这些方法在子组件安装后立即保存在 props 中。


1. 由于这是对完全不同问题的答案,因此我认为将其标记为重复问题没有意义。