The class component passes the ref to the function component
In daily development, we often need to use ref to do some logical processing. Ref is easy to use for current components, but cross-component use, especially now that hooks are widely used and the use of previous classes is cross-referenced, sometimes causes problems. For example, introducing a child in a parent component and passing a ref to a function child will always be empty
The parent component
class Home extends React.Component { childRef = null; render() { return ( <div> <Test ref={ref => this.childRef = ref} /> <Button onClick={() => { console.log(this.childRef) </Button> </div>)}}Copy the code
Subcomponent – Function component
Const callback = (props) => {console.log(props) return (<div> callback component </div>)} export ForwardRef;Copy the code
Child component – Class component
Callback = () => {console.log(' I am the ForwardRef test method ')} render(){return () <div> ForwardRef component </div>) export ForwardRef;Copy the code
As you can see, if you pass a ref to a function component in a class component, it receives undefined, whereas a class component can receive a ref from its parent. How can we pass ref from the class parent to the function child? React’s useImperativeHandle and forwardRef
class Home extends React.Component { childRef = null; render() { return ( <div> <Test ref={ref => this.childRef = ref} /> <Button onClick={() => { if(this.childRef){ Console.log (this.childref.test ())}}> Test call child component method </Button> </div>)}} export default connect()(Home);Copy the code
import React, { useImperativeHandle, forwardRef } from 'react'; const ForwardRef = forwardRef((props, ref) => { console.log(props) useImperativeHandle(ref, () => ({ test, })); Const test = () => {console.log(' I am ForwardRef test method ')} return (<div> ForwardRef </div>)}) export default ForwardRef;Copy the code
This allows you to call the methods of the function’s child components from the class component through ref. Application scenarios such as resetting the form of the child component in the parent component (some separate form validation in the sidebar and popbox, when there are too many page functions, it is recommended that different form validation be placed in different child components).
HOC Component Ref passing (2020.09.28 update)
In react projects, we often use HOC components, such as the error wrapper component for page errors to avoid global crashes. Each component error only displays the current component error, and the whole page does not crash. For example, when the sidebar, popover, TAB switch and so on are opened, if the current component crashes, only the display part of the component that prints the current error will be displayed, and the user experience will not be too bad. There are also global data management that we often use, such as DVA’s Connect wrapper component, which allows components to use dVA’s global state. The current parent component code is as follows:
import React from 'react'; import { connect } from 'dva'; import { Button } from 'antd'; import Test from './component/forwardRef'; class Home extends React.Component { childRef = null; render() { return ( <div> <Test ref={ref => this.childRef = ref} /> <Button onClick={() => { if(this.childRef){ Console.log (this.childref)}}}> Test call child component method </Button> </div>)}} export default connect()(Home);Copy the code
The child components are function components wrapped with CONNECT.
import React, { } from 'react'; import { connect } from 'dva'; Callback = (props) => {console.log(props) const test = () => {console.log(' I am the test method of ForwardRef ')} return ( <div> ForwardRef </div>)} const callback = connect()(ForwardRef) export default ForwardRefWrap;Copy the code
At this point, when the parent component calls the child component through ref, we will find that the print is actually a HOC component wrapped by CONNECT, and we can’t get the child component we really want, let alone call the method of the child component.So how do we call the inner method of a function child? Is it possible to call the same as a normal function component? Try it and see!
import React, { useImperativeHandle, forwardRef } from 'react'; import { connect } from 'dva'; const ForwardRef = forwardRef((props, ref) => { console.log(props) console.log(ref) useImperativeHandle(ref, () => ({ test, })); } return (<div> ForwardRef </div>)}) const callback = () => {console.log(' I am the test method of the ForwardRef ') = connect()(ForwardRef) export default ForwardRefWrap;Copy the code
Code save, run… Take-off from Wuhu !!!!!!!! Error reported directly!! It doesn’t seem to work that way, so how do you use it? Let’s try the following
The parent component is not modified. The parent component’s parent function is called the parent component’s ref (props) function and the parent component’s ref (ref) function is called the parent component’s ref (props) function and the parent component’s ref (REF) function is called the parent component’s REF function. To pass the parent component’s REF to the child component.
import React, { useImperativeHandle, forwardRef } from 'react'; import { connect } from 'dva'; const ForwardRef = (props) => { console.log(props) const {refInstance} = props; useImperativeHandle(refInstance, () => ({ test, })); Return (<div> ForwardRef </div>)} const callback = () => {console.log(' I am the test method of the ForwardRef component ') = connect()(ForwardRef) export default forwardRef((props, ref) => <ForwardRefWrap {... props} refInstance={ref} />);Copy the code
Now that we can call the various methods and states of the children of the ad-wrapped function from ref in the parent component, we can finally have fun