7
const ref = useRef()  

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

here element is a component

like the following

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

getting ref is null in forwardRef...

Reproducible example :- https://codesandbox.io/s/forward-ref-cloneelement-1msjp

Dhanush Bala
  • 1,122
  • 1
  • 14
  • 27
  • Please provide some producible example, also you using hooks with classes which are not likely to compile. Refer to [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) – Dennis Vash Nov 11 '19 at 15:04
  • I noticed you updated the question, you can check my new answer tell me if it helps. – Dennis Vash Nov 21 '19 at 19:30

1 Answers1

7

Try changing innerRef to ref, you adding innerRef property and expecting it to be valid at 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;

Then you can access the ref as you like:

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

Edit:

For class components need to use another key then ref.

There is one caveat to the above example: refs will not get passed through. That’s because ref is not a prop. Like key, it’s handled differently by React. If you add a ref to a HOC, the ref will refer to the outermost container component, not the wrapped component.

// 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


Further, read:

sfletche
  • 47,248
  • 30
  • 103
  • 119
Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • for class component ref is undefined, check here https://codesandbox.io/s/hungry-http-ykb0b – Dhanush Bala Nov 22 '19 at 13:11
  • With classes you need to use other keys like `innerRef`: https://codesandbox.io/s/q-58803654-forwardrefinclass-jve85, edited the answer – Dennis Vash Nov 22 '19 at 13:23
  • i have combination of both class and functional component in my form.. only way to set ref via `RefForm.js` – Dhanush Bala Nov 22 '19 at 13:29
  • Check the sandbox, I made the example for both, and you can see it in the answer too – Dennis Vash Nov 22 '19 at 13:29
  • Why not? Elaborate, you see in both function and class I use `props.innerRef`. https://codesandbox.io/s/frosty-wing-jve85?fontsize=14&hidenavigation=1&theme=dark – Dennis Vash Nov 22 '19 at 13:33
  • if i use `innerRef` in `React.forwardRef` then i will get the following warning ```Warning: forwardRef render functions accept exactly two parameters: props and ref. Did you forget to use the ref parameter?``` – Dhanush Bala Nov 22 '19 at 13:38
  • You don't need the `forwardRef` in case you using the prop, and how is it related to "it doesn't work" when it just a warning? – Dennis Vash Nov 22 '19 at 13:39
  • Here is the complete example, you can see that `Map` has both references although one is function and one is a class. https://codesandbox.io/s/frosty-wing-jve85?fontsize=14&hidenavigation=1&theme=dark – Dennis Vash Nov 22 '19 at 13:40
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/202894/discussion-between-dennis-vash-and-dhanush-bala). – Dennis Vash Nov 22 '19 at 13:41
  • @DennisVash do you know why this might had stopped working? not even printing the 'imHere' inside the function – Jumper Jan 13 '21 at 02:30