通过cloneElement传递forwardRef

时间:2019-11-11 14:49:58

标签: javascript reactjs

const ref = useRef()  

 React.Children.map(this.props.children, (element) => {
   React.cloneElement(element, { 
     innerRef: node => ref,
   })
 })

其中元素是组件

类似于以下内容

const newComponent = forwardRef(({children, ...otherprops}, ref){
    return (
     <div {...otherprops} ref={otherprops.innerRef}>
       {children}
     </div>
    )        
})

在ForwardRef中获取refnull ...

可复制的示例:-https://codesandbox.io/s/forward-ref-cloneelement-1msjp

1 个答案:

答案 0 :(得分:3)

尝试将innerRef更改为ref,添加innerRef属性,并期望它在ref处有效:

import React, { useRef } from 'react';

function RefForm(props) {
  const setRefs = useRef(new Map()).current;
  const { children } = props;
  return (
    <div>
      {React.Children.map(children, child => {
        return React.cloneElement(child, {
//         v not innerRef
          ref: node => {
            console.log('imHere');
            return !node
              ? setRefs.delete(child.key)
              : setRefs.set(child.key, node);
          }
        });
      })}
    </div>
  );
}

export default RefForm;

然后,您可以根据需要增加引用的数量:

const Email = React.forwardRef((props, ref) => {
  console.log('email--', ref);
  ref(); // logs "imHere"
  return (
    <div style={{ marginTop: '30px' }}>
      <label>this is email</label>
      <input name="email" ref={props.innerRef} />
    </div>
  );
});

Edit forward-ref-cloneelement

编辑:

对于类组件,需要使用another key then ref

  

上面的示例有一个警告:引用不会通过。那是因为ref不是道具。像键一样,React对其的处理方式也不同。如果将引用添加到HOC,则引用将引用最外部的容器组件,而不是包装的组件。

// class component
class Name extends Component {
  render() {
    console.log('name--', this.props.innerRef);

    return (
      <div style={{ marginTop: '30px' }}>
        <label>this is name</label>
        <input name="name" ref={this.props.innerRef} />
      </div>
    );
  }
}

// functional component
const Email = props => {
  console.log('email--', props.innerRef);
  return (
    <div style={{ marginTop: '30px' }}>
      <label>this is email</label>
      <input name="email" ref={props.innerRef} />
    </div>
  );
};

// cloneElement
function RefForm(props) {
  const setRefs = useRef(new Map()).current;
  const { children } = props;
  return (
    <div>
      {React.Children.map(children, child => {
        return React.cloneElement(child, {
          innerRef: node => {
            return !node
              ? setRefs.delete(child.key)
              : setRefs.set(child.key, node);
          }
        });
      })}
    </div>
  );
}

Edit Q-58803654-forwardRefInClass