react父子组件传值之二,ref传值(父组件调用子组件的值和方法) useRef+useImperativeHandle(hook)
父组件
import React, { useState, useRef, } from 'react'; import Counter from './four'; import CounterTwo from './five'; export function Three(props) { // 获取子组件实例 const childRef = useRef(); const childRefFive = useRef(); const [fval, setFval] = useState() const [fourval, setFourval] = useState('我是你爸爸') // 调用子组件的onChange方法 const onClickChange = () => { console.log('childRef', childRef) console.log('childRefFive', childRefFive) setFval(childRefFive.current.value) childRef.current.toparent(fourval); // childRef.current.onChange(); }; return ( <div> <h2>父组件</h2> <div>{fval}</div> <button onClick={onClickChange}>我是子组件</button> <Counter ref={childRef} /> <CounterTwo ref={childRefFive} /> </div> ); }
Counter子组件
import React, { useState, useRef, useImperativeHandle, forwardRef, } from 'react'; const Counter = forwardRef((props, ref) => { const [value, setValue] = useState("我是four子组件"); // 自定义暴露给父组件的实例值 (useImperativeHandle 要配合 forwardRef使用) useImperativeHandle(ref, () => ({ // 暴露函数给父组件调用 value, toparent, // 也可以暴露子组件的状态值给父组件使用 })); const toparent = (val) => { console.log('value4', value, val) setValue(val) } return ( <div> {value} {/* <button onClick={() => toparent()}>我是子组件</button> */} <button onClick={toparent}>我是four</button> </div> ) }) export default Counter
CounterTwo子组件
import React, { useState, useRef, useImperativeHandle, forwardRef, } from 'react'; const Counter = forwardRef((props, ref) => { const [value, setValue] = useState("我是five子组件"); // 自定义暴露给父组件的实例值 (useImperativeHandle 要配合 forwardRef使用) useImperativeHandle(ref, () => ({ // 暴露函数给父组件调用 value, toparent, // 也可以暴露子组件的状态值给父组件使用 })); const toparent = (val) => { console.log('value5', value, val) } return ( <div> {value} {/* <button onClick={() => toparent()}>我是子组件</button> */} <button onClick={toparent}>我是four</button> </div> ) }) export default Counter
总结:父组件用useRef返回一个可变的 ref 对象,
子组件必须用useImperativeHandle 要配合 forwardRef使用