3

The current value in the reference object that useRef returns is always null.

I've reproduced the issue here https://codesandbox.io/s/runtime-field-hmusg

I want to get a reference to the component <MyComponent/>

8
  • 1
    Hey, let me know if the solution below works for you :) Commented Sep 5, 2019 at 7:58
  • Yeah, it worked... I wonder why the usage of useRef is not clear in the documentation of react. Also the solution indeed gives a ref to the root div. But what I want to actually do using ref is access child component state variable. How can I do that? Commented Sep 5, 2019 at 8:10
  • Oh you never mentioned any usage of state in your code so I figured that was all your question was. Sure, I can show you how to get those methods as well. Commented Sep 5, 2019 at 8:26
  • 1
    Cool, just wrote out the explanation, let me know if that makes sense. Also, please do consider marking as solution :) Commented Sep 5, 2019 at 9:15
  • 1
    Thanks it worked. This way of accessing states feel more like using access specifiers in Java where you need to explicitly specify what you expose to the outside world. Commented Sep 5, 2019 at 9:54

1 Answer 1

9

You actually need to use the forwardRef method when dealing with functional components. Additionally, there is not a particular clean and easy way to retrieve the state-value of a functional-child component. But here is what you can do:

import React, { useRef, useState, useImperativeHandle } from "react";
import ReactDOM from "react-dom";

function App() {
  const referenceToMyComponent = useRef(null);

  return (
    <div className="App">
      <button
        onClick={() => {
          if (referenceToMyComponent.current) {
            console.log(referenceToMyComponent.current.returnStateValue());
          }
        }}
      >
        Print State reference
      </button>
      <MyComponent ref={referenceToMyComponent} />
    </div>
  );
}

const MyComponent = React.forwardRef((props, ref) => {
  const [count, setCount] = useState(0);

  const returnStateValue = () => {
    return count;
  };

  useImperativeHandle(ref, () => {
    return {
      returnStateValue: returnStateValue
    };
  });

  return (
    <div>
      <h4>Counter: {count}</h4>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
});

Essentially the key-points are the forwardRef, useImperativeHandle, and returnStateValue.

The forwardRef helps us pass a ref coming from a parent to the functional child-component.

The useImperativeHandle hook helps us bind the ref to the instance of the component, we still cannot extract the state-value from the child, but we can access functions defined in the child that would return the state-value anyway.

The returnStateValue function simply returns the state from inside the child-component. We can now access that function via our ref by using referenceToMyComponent.current.returnStateValue()

See working sandbox: https://codesandbox.io/s/dreamy-wiles-xst65

Sign up to request clarification or add additional context in comments.

1 Comment

In my case it not working, I think because I have Redux in the middle. Any solution for that?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.