preface

In React, we often call methods of the parent component in the child component, usually using the props callback. But sometimes you need to call the child’s methods in the parent component to achieve high cohesion. There are many ways, please take as needed.

Type of component

React.createRef()

  • Advantages: easy to understand, with ref point.

  • Disadvantages: Children using HOC are not available and cannot point to real children

    For example, some common notations, such as @Observer wrapped child components of Mobx, do not apply this method.

import React, { Component } from 'react'; Class Sub extends Component {callback() {console.log(' perform callback '); } render() {return <div> subcomponent </div>; } } class Super extends Component { constructor(props) { super(props); this.sub = React.createRef(); } handleOnClick() { this.sub.callback(); } render() { return ( <div> <Sub ref={this.sub}></Sub> </div> ); }}Copy the code

A functional declaration of ref

  • Advantages: REF writing method is concise
  • Disadvantages: Children using HOC are not available and cannot point to real children (same as above)

Use the same method as above, except that the way ref is defined is different.

. <Sub ref={ref => this.sub = ref}></Sub> ...Copy the code

Customize the onRef attribute using props

  • Advantages: If the child component is nested with HOC, it can also point to the real child component.
  • Disadvantages: Need to customize props properties
import React, { Component } from 'react'; Import {observer} from 'mobx-react' @observer class Sub extends Component {componentDidMount() this.props.onRef && this.props.onRef(this); {} callback () the console. The log (" execute me ")} render () {return (< div > subcomponents < / div >). }} class Super extends Component {handleOnClick(){this.sub.callback (); } render(){ return ( <div> <div onClick={this.handleOnClick}>click</div> <Sub onRef={ node => this.Sub = node }></Sub> </div>) } }Copy the code

Function components, Hook components

useImperativeHandle

  • Advantages:

If a child component is nested with HOC, it can also point to a real child component

  • Disadvantages:

2. Need to customize the exposed methods

import React, { useImperativeHandle } from 'react'; import { observer } from 'mobx-react' const Parent = () => { let ChildRef = React.createRef(); function handleOnClick() { ChildRef.current.func(); } return ( <div> <button onClick={handleOnClick}>click</button> <Child onRef={ChildRef} /> </div> ); }; Const Child = observer(props => {useImperativeHandle) useImperativeHandle(props. OnRef, () => {// return {func: func,}; }); Function func() {console.log(' execute me '); } return <div> child component </div>; }); export default Parent;Copy the code

forwardRef

Throws the refs of child components using the forwardRef

This approach is actually better for custom HOC. The problem is that methods like withRouter, connect, and form.create don’t throw refs, and if the Child itself needs to nest these methods, they can’t be mixed. The forwardRef is also used to throw child elements such as ref’s of native elements such as input. It’s not a good idea to throw a component ref because the scenario is too complex.

import React, { useRef, useImperativeHandle } from 'react'; import ReactDOM from 'react-dom'; import { observer } from 'mobx-react' const FancyInput = React.forwardRef((props, ref) => { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); }})); return <input ref={inputRef} type="text" /> }); const Sub = observer(FancyInput) const App = props => { const fancyInputRef = useRef(); Return (< div > < FancyInput ref = {fancyInputRef} / > < button onClick = {() = > fancyInputRef. Current. The focus ()} > parent component calls the child component focus</button> </div> ) } export default App;Copy the code

conclusion

There are two cases of parent tone component functions

  • Child components are not HOC nested: direct calls using REF are recommended
  • HOC nesting: The recommended way to use custom props