一、父子组件都是函数式组件

  1. // 父组件
  2. import React, {useState, useRef } from 'react';
  3. import ClassChild from './classChild'; // 类子组件
  4. const Container = () => {
  5. const cref = useRef()
  6. const [value, setValue] = useState('')
  7. const changeValue = (e) => {
  8. console.log(cref.current) // 取到子组件中的属性
  9. }
  10. return (
  11. <div>
  12. <h1 onClick={changeValue}>test</h1>
  13. <ClassChild ref={cref} />
  14. </div>
  15. )
  16. }
  17. export default Container;
  18. // 子组件
  19. import React, { useState, useImperativeHandle, forwardRef } from 'react';
  20. const Container = (props, ref) => {
  21. let [data,setData] = useState(12);
  22. const changeValue = (e) => {
  23. console.log(data);
  24. }
  25. useImperativeHandle(ref, () => ({
  26. changeValue,
  27. }))
  28. return (
  29. <div>
  30. <h1 onClick={changeValue}>test{data}</h1>
  31. </div>
  32. )
  33. }
  34. export default forwardRef(Container);

二、父组件是类组件、子组件是函数式组件

这种情况时:
父组件正常创建ref, 子组件接收时有所变动

  1. // 父组件
  2. constructor() {
  3. super();
  4. this.containerRef = React.createRef()
  5. }
  6. const test = () => {
  7. console.log(this.containerRef)
  8. this.containerRef.current.handleClear()
  9. console.log(this.containerRef.current.inputValue)
  10. }
  11. render() {
  12. <div>
  13. <button onClick={this.test}>test</button>
  14. <Container ref={this.containerRef} />
  15. </div>
  16. }
  17. // 子组件
  18. // 利用useImperativeHandle、forwardRef 两个hooks钩子来接收绑定
  19. import React, {useState, useRef, useImperativeHandle, forwardRef } from 'react';
  20. const Container = (props,ref) => {
  21. const cref = useRef()
  22. const [value, setValue] = useState('')
  23. const handleClear = () => {
  24. console.log('handle clear')
  25. }
  26. useImperativeHandle(ref, () => ({
  27. handleClear,
  28. inputValue: cref.current.value
  29. }))
  30. const changeValue = (e) => {
  31. setValue(e.target.value)
  32. }
  33. return (
  34. <div>
  35. <h1>test</h1>
  36. <input ref={cref} value = {value} onChange={changeValue}></input>
  37. </div>
  38. )
  39. }
  40. export default forwardRef(Container);

三、父组件是函数式组件、子组件是类组件

这种情况只需要处理父组件就可以,子组件不需要处理
父组件:

  1. import React, {useState, useRef } from 'react';
  2. import ClassChild from './classChild'; // 类子组件
  3. const Container = () => {
  4. const cref = useRef()
  5. const [value, setValue] = useState('')
  6. const changeValue = (e) => {
  7. console.log(cref.current) // 取到子组件中的属性
  8. }
  9. return (
  10. <div>
  11. <h1 onClick={changeValue}>test</h1>
  12. <ClassChild ref={cref} />
  13. </div>
  14. )
  15. }
  16. export default Container;

四、父子组件都是函数式组件:

  1. constructor() {
  2. super();
  3. this.containerRef = React.createRef()
  4. }
  5. const test = () => {
  6. console.log(this.containerRef)
  7. this.containerRef.current.handleClear()
  8. console.log(this.containerRef.current.inputValue)
  9. }
  10. render() {
  11. <div>
  12. <button onClick={this.test}>test</button>
  13. <Container onRef={(ref) => {this.containerRef = ref}} />
  14. </div>
  15. }
  16. // 子组件
  17. // 将子组件的this 传回去
  18. componentDidMount() {
  19. this.props.onRef(this)
  20. }

总结来说:
函数式组件作为子组件的时候需要借助两个钩子来处理, 即useImperativeHandle, forwardRef
函数式组件作为父组件的时候需要借助钩子 useRef