Calling a function in a child or sibling component in React

“How to call a function in child or sibling component” is a fairly frequently asked question in React world. This is how we’ve solved it.

The setup is this: we have a parent component and one or two child components. We need to raise an event in a child component either from the parent component, or we need a child component A to raise an event in child component B.

Raising an event in the parent component from the child component is trivial – the parent component can pass a reference to the function to the child as a prop, and the child component will call it at will.

This is the basic code:

a Parent will pass onCountChanged function to the CountProvider component; CountProvider calls this function with a new value, parent displays the value.

CodeSandbox

This works because parent can pass props to the child components. This is a one way communication, though, so what do you do when you need a parent (or, by extension, sibling component) to call a function in a child component?
Take a look at the code below and I’ll explain what’s going on.

CodeSandbox

We have 3 components: a parent component and CountControl and CountDisplay components. Let’s say CountDisplay needs to react to something happening in CountControl (we’re assuming that it needs to react to an event, and passing the state wouldn’t work).

CountControl notifies parent about the event in the usual way – parent passes in the function, CountControl runs it with parameters when stuff happens.

Now we need to take this and let the CountDisplay know that stuff has happened. This is a bit more involved, but not by much.

  • Let’s define a receiver function in Parent (I’ve made it to a no-op function, but it can be initialized to null – it will get reassigned later on anyways).
  • Then let’s create a function receiverCreator that will take another function (with the same signature as receiver) as a parameter, and assign that function to receiver.
  • Pass receiverCreator to CountDisplay.
  • In CountDisplay, create onCountReceived function that will do stuff in response to the event, and execute receiverCreator, passing a reference to onCountReceived as a parameter.

This is a little convoluted, but take a look at the code – it’s not complicated. The result is parent having a reference to the function inside of the child component, which can be executed by parent – and, by extension, it can be triggered by other child components.

This specific scenario could be solved with forwardRefs, more or less, but add some complexity (e.g. we need to respond to something more involved than a button click), and it doesn’t work that well.

Also, in a lot of cases, this can be solved with passing the state either via props or in Redux. Sometimes there’s a need to react to an event, so checking for state changes isn’t ideal.

Thoughts/comments?

Leave a Reply

Your email address will not be published. Required fields are marked *