Using a React Component’s function from its Parent

React offers an awesome toolset that allows you to effectively break up and modularize your applications into smaller pieces that work together. This allows us developers to breakout functionality and keep it in one location.

While this way of archit…

React offers an awesome toolset that allows you to effectively break up and modularize your applications into smaller pieces that work together. This allows us developers to breakout functionality and keep it in one location.

While this way of architecting allows for amazing levels of flexibility and maintainability, we all will eventually hit this scenario: What if I want one custom React component to trigger a function that lives in one of its custom Child components?

Using React’s forwardRef API along with the built-in hook useImperativeHandle, this is simple to do!

This tutorial assumes you have some basic knowledge of React and how to use it.



Setting up our Components

To demonstrate, we’re going to build a simple component that presents you with some color options and a box. Clicking on the color buttons will change the color of the box.

Box changing colors when buttons are clicked

The header and buttons of our component will live in the Parent component, while the color-shifting box and the functionality to change the box’s color will be held in the Child component. Here’s what that looks like:

import { useState } from 'react'
const Parent = () => {
    return (
        <div className="flex flex-col gap-4 min-h-screen bg-gray-200 justify-center items-center">
            <h2 className="text-gray-500 text-2xl font-bold text-30">What color should the box be?</h2>
            <div className="flex justify-between w-80">
                <button className="bg-blue-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Blue</button>
                <button className="bg-green-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Green</button>
                <button className="bg-red-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Red</button>
                <button className="bg-yellow-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Yellow</button>
            </div>
            <Child/>
        </div>
    )
}

const Child = () => {
    const [ color, setColor ] = useState('bg-blue-300')
    const changeColor = color => {
        setColor(color)
    }
    return <div className={`w-40 h-40 transition-colors duration-900 ease-in-out rounded-2xl ${color}`}></div>
}

NOTE: I’m using TailwindCSS for some quick styling

There’s nothing too crazy going on here, just rendering out our Parent and Child. The Child has a function to update the color of its box, and some state to hold that setting. For now the buttons don’t do anything, the box is blue… boring! Let’s bring this thing to life!



Reference the Child

First thing’s first, we need to somehow reference the Child component to get access to its properties. React’s useRef hook does exactly that. To create a reference to the Child component, we’ll need to import that hook from react, create a reference, and apply that reference to the component.

// Added useRef to our imports
import { useState, useRef } from 'react'

const Parent = () => {
    // Set up our reference
    const boxRef = useRef(null)

    return (
        <div className="flex flex-col gap-4 min-h-screen bg-gray-200 justify-center items-center">
            <h2 className="text-gray-500 text-2xl font-bold text-30">What color should the box be?</h2>
            <div className="flex justify-between w-80">
                <button onClick={() => boxRef.current.changeColor('bg-blue-300')} className="bg-blue-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Blue</button>
                <button onClick={() => boxRef.current.changeColor('bg-green-300')} className="bg-green-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Green</button>
                <button onClick={() => boxRef.current.changeColor('bg-red-300')} className="bg-red-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Red</button>
                <button onClick={() => boxRef.current.changeColor('bg-yellow-300')} className="bg-yellow-400 py-2 px-4 focus:outline-none rounded-xl text-white font-bold">Yellow</button>
            </div>
            {/* Apply the reference to our component */}
            <Child ref={boxRef}/>
        </div>
    )
}

We now have a reference set up that should give us access to the properties of the Child. This reference has a property named .current that is set to value of the DOM node of the component it is attached to, giving it access to its properties.
I went ahead and added the click-handlers on each button to trigger the changeColor function in the Child component. Let’s try it out:

Forward Ref Error Message

Oof, it blew up! ? What’s going on?

The reason this won’t work, and the thing that makes this process tricky, is that the ref property on our <Child/> component is not a normal “prop”. React handles ref differently than it handles most other props and doesn’t pass it through to the Child in the props object.



forwardRef To The Rescue

To get this to work properly, we need to “forward” our ref to the Child component. Luckly, React has a nice API called forwardRef that allows exactly that.

To use this API, we need to import it from react and wrap our Child component in the forwardRef function. This function takes in props and ref parameters and returns the Child component.

// Added forwardRef to the import list
import { forwardRef, useState, useRef } from 'react'
const Child = forwardRef((props, ref) => {
    const [ color, setColor ] = useState('bg-blue-300')
    const changeColor = color => {
        setColor(color)
    }
    return <div className={`w-40 h-40 transition-colors duration-900 ease-in-out rounded-2xl ${color}`}></div>
})

This will pass along our ref to the Child component, but now we need to expose our changeColor function to the Parent component through that ref. To do that we will need to use useImperativeHandle, a hook that React provides. This hook takes in a ref param and a function that allows you to expose custom properties to the Parent through that ref. Here it is in action:

// Added useImperativeHandle to our imports
import { forwardRef, useState, useRef, useImperativeHandle } from 'react'
const Child = forwardRef((props, ref) => {
    const [ color, setColor ] = useState('bg-blue-300')
    useImperativeHandle(ref, () => ({
      changeColor: color => {
          setColor(color)
      }
    }))
    return <div className={`w-40 h-40 transition-colors duration-900 ease-in-out rounded-2xl ${color}`}></div>
})

We now have forwarded our ref into the Child component and customized the the instance that is exposed to the Parent component, giving it access to a function that will update the Child’s state to change the color of our box.

Save that and give ‘er a go!

Box changing colors when buttons are clicked

Fancy! Our “handle” into the Child component is accessible from our Parent component and allows us to update the child’s state through the function we’ve exposed via that “handle”.



Conclusion

Using React’s forwardRef API and useImperativeHandle hook, we gain the flexibility to allow for even greater component interactions, adding to the awesome flexibility of the React library. This is useful for a TON of different things, especially when developing component libraries with things such as Alerts, Modals, etc…

Thanks so much for giving this a read, I hope it was helpful!

If you liked this, be sure to follow me on Twitter to get updates on new articles I write!


Print Share Comment Cite Upload Translate
APA
Sabin Adams ??‍? | Sciencx (2024-03-29T14:26:58+00:00) » Using a React Component’s function from its Parent. Retrieved from https://www.scien.cx/2021/05/22/using-a-react-components-function-from-its-parent/.
MLA
" » Using a React Component’s function from its Parent." Sabin Adams ??‍? | Sciencx - Saturday May 22, 2021, https://www.scien.cx/2021/05/22/using-a-react-components-function-from-its-parent/
HARVARD
Sabin Adams ??‍? | Sciencx Saturday May 22, 2021 » Using a React Component’s function from its Parent., viewed 2024-03-29T14:26:58+00:00,<https://www.scien.cx/2021/05/22/using-a-react-components-function-from-its-parent/>
VANCOUVER
Sabin Adams ??‍? | Sciencx - » Using a React Component’s function from its Parent. [Internet]. [Accessed 2024-03-29T14:26:58+00:00]. Available from: https://www.scien.cx/2021/05/22/using-a-react-components-function-from-its-parent/
CHICAGO
" » Using a React Component’s function from its Parent." Sabin Adams ??‍? | Sciencx - Accessed 2024-03-29T14:26:58+00:00. https://www.scien.cx/2021/05/22/using-a-react-components-function-from-its-parent/
IEEE
" » Using a React Component’s function from its Parent." Sabin Adams ??‍? | Sciencx [Online]. Available: https://www.scien.cx/2021/05/22/using-a-react-components-function-from-its-parent/. [Accessed: 2024-03-29T14:26:58+00:00]
rf:citation
» Using a React Component’s function from its Parent | Sabin Adams ??‍? | Sciencx | https://www.scien.cx/2021/05/22/using-a-react-components-function-from-its-parent/ | 2024-03-29T14:26:58+00:00
https://github.com/addpipe/simple-recorderjs-demo