Web 开发
2022-04-12

React 父组件获取子组件值的四种方式

次点击
15分钟阅读

子组件获取父组件的值都知道,最基本的就是通过 props 传值即可,同样也可以使用 context 由于是单向数据流,那么父组件是怎么获取子组件的值呢。

类组件函数组件都进行梳理

均为类组件

使用 ref

import React, { Component } from 'react';
import ChildClass from './ChildClass';
class FatherClass extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.child = React.createRef();
  }
  getValue = () => {
    console.log('this.child', this.child);
  };
  render() {
    return (
      <div>
        <ChildClass ref={this.child} />
        <button onClick={this.getValue}>获取输入框内容</button>
      </div>
    );
  }
}
export default FatherClass;
import React, { Component } from 'react';
class ChildClass extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ''
    };
  }
  handleChange = (e) => this.setState({ value: e.target.value });
  render() {
    const { value } = this.state;
    return (
      <div>
        <input value={value} onChange={this.handleChange} />
      </div>
    );
  }
}
export default ChildClass;

打印的日志如下

image.png

这样就可以获取子组件的所有值

均为函数组件

import React, { useRef } from 'react';
import ChildFun from './ChildFun';
function FatherFun() {
  const childRef = useRef();
  const getValue = () => {
    console.log('childRef', childRef);
  };
  return (
    <div>
      <ChildFun ref={childRef} />
      <button onClick={getValue}>获取输入框内容</button>
      <button onClick={() => childRef.current?.handleChange('666')}>
        父组件修改输入框的值为666
      </button>
    </div>
  );
}
export default FatherFun;
import React, { useState, forwardRef, useImperativeHandle } from 'react';
function ChildFun(props, ref) {
  const [value, setValue] = useState('');
  const handleChange = (e) => {
    setValue(e.target.value);
  };
  useImperativeHandle(ref, () => ({
    value,
    handleChange: (res) => setValue(res)
  }));
  return (
    <div>
      <input value={value} onChange={handleChange} />
    </div>
  );
}
export default forwardRef(ChildFun);

打印的日志如下 image.png 与类组件不同的是

  1. 父组件使用 useRef 创建 ref
  2. 子组件需要使用 useImperativeHandleforwardRef
  3. useImperativeHandle可以在使用 ref 时自定义暴露给父组件的实例值 (也就是说只有valuehandleChange 会暴露给父组件,组件其他的内容不会暴露给父组件)

父组件是类组件,子组件是函数组件

这种方式很常见,只需将上面代码中 FatherClassChildFun 这两个组件组合即可

import React, { Component } from 'react';
import ChildFun from './ChildFun';
class FatherClass extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    this.child = React.createRef();
  }
  getValue = () => {
    console.log('this.child', this.child);
  };
  render() {
    return (
      <div>
        <ChildFun ref={this.child} />
        <button onClick={this.getValue}>获取输入框内容</button>
        <button onClick={() => this.child.current?.handleChange('666')}>
          父组件修改输入框的值为666
        </button>
      </div>
    );
  }
}
export default FatherClass;
import React, { useState, forwardRef, useImperativeHandle } from 'react';
function ChildFun(props, ref) {
  const [value, setValue] = useState('');
  const handleChange = (e) => {
    setValue(e.target.value);
  };
  useImperativeHandle(ref, () => ({
    value,
    handleChange: (res) => setValue(res)
  }));
  return (
    <div>
      <input value={value} onChange={handleChange} />
    </div>
  );
}
export default forwardRef(ChildFun);

打印的日志如下 image.png

父组件是函数组件,子组件是类组件

import React, { useRef } from 'react';
import ChildClass from './ChildClass';
function FatherFun() {
  const childRef = useRef();
  const getValue = () => {
    console.log('childRef', childRef);
  };
  return (
    <div>
      <ChildClass ref={childRef} />
      <button onClick={getValue}>获取输入框内容</button>
      <button onClick={() => childRef.current?.customChange('666')}>
        父组件修改输入框的值为666
      </button>
    </div>
  );
}
export default FatherFun;
import React, { Component } from 'react';
class ChildClass extends Component {
  constructor(props) {
    super(props);
    this.state = {
      value: ''
    };
  }
  customChange = (res) => {
    this.setState({
      value: res
    });
  };
  handleChange = (e) => this.setState({ value: e.target.value });
  render() {
    const { value } = this.state;
    return (
      <div>
        <input value={value} onChange={this.handleChange} />
      </div>
    );
  }
}
export default ChildClass;