React Ref 和 高阶组件

Refs:可以用来访问DOM节点或者React组件

一、React.createRef():在类组件中创建refs,并通过 ref 属性附加到 React 元素上,附加到React元素上后,通过refs的current属性访问实例。React.useRef():在函数组件中创建refs,使用方法一样
  • 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
  • class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        // 在构造函数中创造一个refs
        this.myRef = React.createRef(); 
     focusTextInput() {
        //通过 "current" 来访问 DOM 节点
        this.myRef.current.focus();
      render() {
        // 将myRef绑定到input DOM元素上
        return (<div  onClick={this.focusTextInput}>
          <input
              type="text"
              ref={this.myRef} />
        </div>)
    
  • 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性,通过current属性可以访问类组件上的属性和方法。
  • class Child extends React.Component {
      testFunc(){
        console.log('子组件上的方法');
    class Parent extends React.Component {
      constructor(props) {
        super(props);
        this.myRef= React.createRef();
      componentDidMount() {
        // 通过this.myRef.current 访问绑定ref的类组件上的方法
        this.myRef.current.testFunc();
      render() {
        return (
          <Child ref={this.myRef} />
    将 ref 属性直接设置在函数组件身上,不会有任何作用,因为他们没有实例
    
    二、React.forwardRef((props,ref)=>...)是一个高阶组件,参数是一个函数组件,会将原函数props中的ref属性拎出来作为新函数组件的第二个参数,并返回这个新的函数组件,ref属性会附加到新的函数组件上,同样,在该函数组件中,ref属性可以绑定到DOM元素或Class组件上
    // React.forwardRef包裹函数组件
    const FancyButton = React.forwardRef((props, ref) => (
      <button ref={ref} className="FancyButton">
        {props.children}
      </button>
    // ref传递给FancyButton 
    const ref = React.createRef();
    <FancyButton ref={ref}>Click me!</FancyButton>;
    

    当ref挂在完成,ref.current将指向<button>DOM节点

    如果要在函数组件上使用 ref,直接将ref绑定到函数组件,可以使用forwardRef与 useImperativeHandle实现
    useImperativeHandle自定义暴露给父组件的实例值

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