我有两个组成部分:

父组件 子组件

我试图从Parent调用Child的方法,我尝试了这种方式,但不能得到一个结果:

class Parent extends Component {
  render() {
    return (
      <Child>
        <button onClick={Child.getAlert()}>Click</button>
      </Child>
      );
    }
  }

class Child extends Component {
  getAlert() {
    alert('clicked');
  }
 
  render() {
    return (
      <h1 ref="hello">Hello</h1>
    );
  }
}

是否有一种方法从父调用子方法?

注意:子组件和父组件在两个不同的文件中。


当前回答

逻辑很简单。

在父类中使用child或ref创建一个函数。

我更喜欢父用子的创建功能。有很多种方法。

使用功能组件时

在父

function Parent(){
  const [functionToCall, createFunctionToCall] = useState(()=>()=>{})

  return (
   <Child createFunctionToCall={createFunctionToCall} />
  )
}

在儿童

function Child({createFunctionToCall}){
  useEffect(()=>{
    function theFunctionToCall(){
      // do something like setting something
      // don't forget to set dependancies properly.
    }
    createFunctionToCall(()=>theFunctionToCall)
  },[createFunctionToCall])
}

其他回答

这个模式类似于@brickingup answer。但是在这个版本中,你可以设置任意多的子动作。

import { useEffect } from "react";

export const Parent = () => {
  const childEvents = { click: () => {} };

  return (
    <div onClick={() => childEvents.click()}>
      <Child events={childEvents}></Child>
    </div>
  );
};

export const Child = (props) => {
  const click = () => {
    alert("click from child");
  };

  useEffect(() => {
    if (props.events) {
      props.events.click = click;
    }
  }, []);

  return <span>Child Component</span>;
};

在这里,我将给出四种可能的组合:

类父类|钩子子类 钩子父类|类子类 钩父钩子 类父类|类子类

1. 类父类|钩子子类

class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.myRef = React.createRef()
  }

  render() {
    return (<View>
      <Child ref={this.myRef}/>
      <Button title={'call me'}
              onPress={() => this.myRef.current.childMethod()}/>
    </View>)
  }
}

const Child = React.forwardRef((props, ref) => {

  useImperativeHandle(ref, () => ({
    childMethod() {
      childMethod()
    }
  }))

  function childMethod() {
    console.log('call me')
  }

  return (<View><Text> I am a child</Text></View>)
})

2. 钩子父类|类子类

function Parent(props) {

  const myRef = useRef()

  return (<View>
    <Child ref={myRef}/>
    <Button title={'call me'}
            onPress={() => myRef.current.childMethod()}/>
  </View>)
}

class Child extends React.Component {

  childMethod() {
    console.log('call me')
  }

  render() {
    return (<View><Text> I am a child</Text></View>)
  }
}

3.钩父钩子

function Parent(props) {

  const myRef = useRef()

  return (<View>
    <Child ref={myRef}/>
    <Button title={'call me'}
            onPress={() => myRef.current.childMethod()}/>
  </View>)
}

const Child = React.forwardRef((props, ref) => {

  useImperativeHandle(ref, () => ({
    childMethod() {
      childMethod()
    }
  }))

  function childMethod() {
    console.log('call me')
  }

  return (<View><Text> I am a child</Text></View>)
})

4. 类父类|类子类

class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.myRef = React.createRef()
  }

  render() {
    return (<View>
      <Child ref={this.myRef}/>
      <Button title={'call me'}
              onPress={() => this.myRef.current.childMethod()}/>
    </View>)
  }
}

class Child extends React.Component {

  childMethod() {
    console.log('call me')
  }

  render() {
    return (<View><Text> I am a child</Text></View>)
  }
}

https://facebook.github.io/react/tips/expose-component-functions.html 更多答案请参考这里调用React子组件上的方法

通过查看“reason”组件的引用,您正在破坏封装,如果不仔细检查使用该组件的所有位置,就不可能重构该组件。正因为如此,我们强烈建议将引用视为组件的私有,就像状态一样。

一般来说,数据应该通过道具沿着树向下传递。有一些例外情况(比如调用.focus()或触发一个不会真正“改变”状态的一次性动画),但任何时候你要公开一个名为“set”的方法,道具通常是更好的选择。试着让内部输入组件担心它的大小和外观,这样它的祖先就不会担心。

你可以很容易地使用你的子组件作为react自定义钩子来应用这个逻辑。

如何实施?

子函数返回一个函数。 子函数返回JSON:{函数、HTML或其他值}作为示例。

在这个例子中,应用这个逻辑没有意义,但很容易看出:

const {useState} = React; //Parent const Parent = () => { //custome hook const child = useChild(); return ( <div> {child.display} <button onClick={child.alert}> Parent call child </button> {child.btn} </div> ); }; //Child const useChild = () => { const [clickCount, setClick] = React.useState(0); {/* child button*/} const btn = ( <button onClick={() => { setClick(clickCount + 1); }} > Click me </button> ); return { btn: btn, //function called from parent alert: () => { alert("You clicked " + clickCount + " times"); }, display: <h1>{clickCount}</h1> }; }; const rootElement = document.getElementById("root"); ReactDOM.render(<Parent />, rootElement); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <div id="root"></div>

逻辑很简单。

在父类中使用child或ref创建一个函数。

我更喜欢父用子的创建功能。有很多种方法。

使用功能组件时

在父

function Parent(){
  const [functionToCall, createFunctionToCall] = useState(()=>()=>{})

  return (
   <Child createFunctionToCall={createFunctionToCall} />
  )
}

在儿童

function Child({createFunctionToCall}){
  useEffect(()=>{
    function theFunctionToCall(){
      // do something like setting something
      // don't forget to set dependancies properly.
    }
    createFunctionToCall(()=>theFunctionToCall)
  },[createFunctionToCall])
}