React Hook parent component retrieves data/functions of child components

We know that in react, props are often used to transfer child component data to parent component, but the function of parent component calling child component is not often used. Documentation says ref is not the best choice, but thinking of laziness and not learning redux, I found many tutorials on the Internet. Either the hook talks too little, or the father and son components are silly and confused, so I had to gnaw the document again and learn the api of other hooks.
Here we need to use the useImperativeHandle api in the form of a function

useImperativeHandle(ref, createHandle, [deps])

In fact, this api is also a form of ref, but it is equivalent to doing some optimization, you can choose to let the sub-component only expose a certain api to the parent component, according to the method given in the document and other blogs, there are two steps:

  1. Pass ref to subcomponents
  2. Subcomponents need to be wrapped using forward Ref

Subcomponent MyWorldMap

 const mapRef = useRef(null);
    useImperativeHandle(ref, () => {

        return {
            //clickSwitch is a function exposed by subcomponents
            clickSwitch() {
             
                if(type == 1){
                    initChinaMap();
                    setType(2);
                }else{
                    initWordMap();
                    setType(1);
                }
              
            }
        }
    })

//Your return content, pay attention to ref

    return(
        <React.Fragment>

            <div id={"myWorldMap"} style={{ width: "800px", height: "400px" }}  ref={mapRef}></div>

        </React.Fragment>


    )
}


//Finally, cooperate with forward Ref
MyWorldMap = forwardRef(MyWorldMap);
export default MyWorldMap;

Note: ref is passed in when a subcomponent is declared, that is

function MyWorldMap (props,ref){
//... Your code
}

//export...

In fact, the official documents give examples of:

function FancyInput(props, ref) {
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    }
  }));
  return <input ref={inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

Both methods are possible.

Parent component MyTrip

const myWordMapRef = useRef();

return(
  //Omit some code and pay attention to ref
 <MyWorldMap proData = { myMapData} handleMapClick = {handleMapClick.bind(this)} ref={myWordMapRef}>

 </MyWorldMap>
<div className={styles["mapButton-wrap"]}>
       <ButtonGroup>
               <Button onClick={() => myWordMapRef.current.clickSwitch()}>Switch</Button>
               <Button onClick={()=>clickAll() }>All</Button>
        </ButtonGroup>
 </div>
)

Now you can call the function in the parent component through myWordMapRef.current.clickSwitch().

Tags: Javascript React Fragment

Posted on Sat, 05 Oct 2019 23:46:06 -0700 by tjodolv