4

I tried the following code but it fails So, this is my Parent Component:

    import React from 'react'
import ChildComponent from './ChildComponent';

const ParentComponent = (props) => {

    //step 1
    // const inputRef = React.createRef();
    const buttonRef = React.useRef();
    const focusHandler = () => {
        alert("hi");
    }

    return (
        <div>
            {/* In parent, we generally pass reference to child which we dint do here, lets see if props children help here */}
            {props.children}
            <ChildComponent ref="buttonRef" />

        </div>
    )
}

export default ParentComponent;

This is my child component:

import React from 'react'

const ChildComponent = React.forwardRef((props, ref) => {
    return (
        <div>
            <button onClick={ref.focusHandler}>Focus Input</button>      
        </div>
    )
})

export default ChildComponent;

On click of the button above in child component, I wish to call Parent method. How can that be achieved? EDITED

skyboyer
  • 22,209
  • 7
  • 57
  • 64
sakshinarang
  • 99
  • 3
  • 14

3 Answers3

3

The reason you're getting the error is because refs in function components need to be passed using ref={buttonRef}, not ref="buttonRef". Class components have a thing they can do with string refs, but it's not recommended even there.

As for calling a function from a parent component, you don't need refs to do this. So if that was the only reason you were using a ref, you can remove the ref. Instead, pass the function as a prop:

const ParentComponent = (props) => {
    const focusHandler = () => {
        alert("hi");
    }

    return (
        <div>
            <ChildComponent focusHandler={focusHandler} />
        </div>
    )
}

const ChildComponent = (props) => {
    return (
        <div>
            <button onClick={props.focusHandler}>Focus Input</button>      
        </div>
    )
}
Nicholas Tower
  • 72,740
  • 7
  • 86
  • 98
  • Thanks. That was a silly mistake. Although, have corrected it. No more getting that error. But, after that, the error is but the main query, not able to receive alert. Have changed button to But this didn't help either – sakshinarang Jul 05 '20 at 10:26
  • Still, wanted to do this via ForwardRef concept if you know. This is basic concept in which prop is being passed – sakshinarang Jul 05 '20 at 11:21
  • 1
    ForwardRef is not about passing data from the parent to the child, and you should not use it for that. The purpose of forward ref is so that the *parent* component can get a reference to a dom element in the *child* component. Usually it would be the outermost dom element (the child's `
    ` in your case). This is for the parent's benefit, not the child's. It lets the parent then do imperative things things like call `.focus` on that element, or scroll the element into view
    – Nicholas Tower Jul 05 '20 at 14:49
1

Just replace ref by focusHandler like below in parent component

<ChildComponent focusHandler={focusHandler} />

Then in ChildComponent, remove ref as well.

ShinaBR2
  • 2,519
  • 2
  • 14
  • 26
  • This dint help either In child component, still onClick event ref is to be triggered right? How? If ref is "focusHandler" as you mentioned – sakshinarang Jul 05 '20 at 10:30
  • I mean no need to use `ref` at all in your `ChildComponent`, just ONLY need `focusHandler`. – ShinaBR2 Jul 05 '20 at 10:32
  • Another related question here: https://stackoverflow.com/questions/28889826/how-to-set-focus-on-an-input-field-after-rendering – ShinaBR2 Jul 05 '20 at 10:36
  • import React from 'react' const ChildComponent = () => { return (
    ) } export default ChildComponent; What's to be written **onClick** ?
    – sakshinarang Jul 05 '20 at 10:36
  • Just like this: `````` – ShinaBR2 Jul 05 '20 at 10:37
1

If you wonder how to use refs in this case (even though this is not the recommended way to pass callbacks), you need to assign focusHandler key and use the ref with ref.current, refer to Components and Props docs.

const ParentComponent = () => {
  const buttonRef = React.useRef({ focusHandler: () => alert("hi") });

  return (
    <div>
      <ChildComponent ref={buttonRef} />
    </div>
  );
};

const ChildComponent = React.forwardRef((props, ref) => {
  return (
    <div>
      <button onClick={ref.current.focusHandler}>Focus Input</button>
    </div>
  );
});

Edit blissful-leaf-emm72

Dennis Vash
  • 50,196
  • 9
  • 100
  • 118
  • Thanks!! what do we do if we have ChildComponent in main page as and the method is in ParentComponent – sakshinarang Jul 05 '20 at 11:49
  • 1
    Don't understand the question, anyway you should just post a new question with some context. – Dennis Vash Jul 05 '20 at 11:50
  • Try reading the answer until the end "you don't need refs to pass callbacks" OP especially asks how to use `forwardRef` – Dennis Vash Jul 05 '20 at 14:12
  • @NicholasTower She even told it in her own comment for your answer: "Still, wanted to do this via ForwardRef concept if you know. This is basic concept in which prop is being passed " – Dennis Vash Jul 05 '20 at 14:13