DEV Community

JafetMeza
JafetMeza

Posted on

How to send data from a child component to a parent component in react?

To reach this goal we have to be aware about two different functions in react, useImperativeHandle and forwardRef.
I will not explain what are this function individually, it is better if we see it as a group.

When we use useImperativeHandle, the code will work until you use forwarRef in the same component, you will see an error like this if you are not using it.

Image description


To have better explanation of how to do it, let's do some code.

Imagine you need a button and this button have to save the amount of clicks that the user presses but we have to access this information only with another button in the same page, so basically we will have something like this.

Image description

First let's create the children component

import { forwardRef, useImperativeHandle, useState } from "react";
import PropTypes from "prop-types";

const CustomButton = forwardRef(
  ({ className, action = () => {}, children }, ref) => {
    const [count, setCount] = useState(0);

    // we are returning a function inside the ref
    // to returning the count of clicks
    useImperativeHandle(ref, () => ({
      getCount() {
        return count;
      },
    }));
    return (
      <button
        className={`button ${className}`}
        onClick={() => {
          setCount((count+= 1)); // we count the clicks
          action();
        }}
      >
        {children}
      </button>
    );
  }
);
// This line is because we get a warning
// When we use forwardRef we always have to have displayName
CustomButton.displayName = "Custom Button";

CustomButton.propTypes = {
  className: PropTypes.string.isRequired,
  action: PropTypes.func.isRequired,
};

export default CustomButton;
Enter fullscreen mode Exit fullscreen mode

If you notice in the useImperativeHandle function we are returning a function call getCount() which returns the amount of clicks, but now maybe you are wondering how to use this component. Let's create the parent component.

import { useRef } from "react";
import CustomButton from "../components/customButton";

export default function Example() {
  // we create a reference to the first button
  const button1 = useRef();

  // function of the first button
  const onClick = () => {
    console.log("do some action");
  };

  // function of the second button
  const onClick2 = () => {
    // we get the count with the reference of the first button
    console.log(ref.current.getCount());
  };

  return (
    <>
      <CustomButton ref={button1} action={onClick} className="is-success">
        Button 1
      </CustomButton>
      <CustomButton action={onClick2} className="is-danger mt-3">
        Get count of button 1
      </CustomButton>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the function of the second button gets the count of the first button, but let run it and do some clicks and see the console.
Image description
The console says we have press the button 9 times, now let's press the second button.
Image description
We get the amount successfully! But let's do some more to see if we still get the right answer.
Image description

Conclusion

We can return anything from our children components, like a function as we did, or objects, string, and if you want we can return elements of the DOM or even another references, the power of this is pretty amazing.
There is another approach of passing data from a children to a parent but this is for another post...

Thank you so much for reading and feel free to contact me if you need anything.

Top comments (1)

Collapse
 
alan_anaya profile image
Alan Anaya Araujo

Well explained and it works everything correctly, nice keep doing great!