Can you wrap your head around how components in React.js communicate with each other?
Let me help you out.
In this tutorial, we're going to build this application:
You can find the full source code in this GitHub repository.
Our application is going to render a message with a
Love button. When you clicks
Love button our heart icon "turns on" and our button's text is changed to
As you can see our application will need to render 2 different states: 1) when message is loved and 2) when message is unloved.
Our application will be made of 3 React.js components:
Button components are siblings and both are nested inside of
Can you tell which component will own the state for the whole application?
Let's think about it. When user interacts with the
Button component, our
Message component needs to react and render differently. How can we achieve this when
Message components are siblings?
The answer is: our
MessageContainer will be in charge of maintaining our application's state. And since
MessageContainer is a parent component for both
Button components - it can pass that state to them too.
When user interacts with the
Button component, it will update
MessageContainer's state and re-render both
Message component first:
Wait, what is this
statelessFunctionComponentClass function is doing here - where is
React.createClass? That's how you create component class in React - by calling
That's right, but in version 0.14 React introduced a new way of creating components using functions. These components will be stateless components without any lifecycle methods and other boilerplate. Which means they can be optimised for speed.
Message component will be stateless and we don't need to access any component lifecycle methods, so the functional way of creating
Message component is a perfect choice in this case.
Notice that we've named our function
statelessFunctionComponentClass - this is just for signaling the fact that we're using a functional way of creating our component class.
statelessFunctionComponentClass function declares
props parameter - this is a way for
Message component to access properties passed to it by a parent component.
What is the purpose of our
Message component? To render message text and an icon that represents whether the message is loved or not loved.
Let's implement that:
The first thing is to get a path string to an image file that visualizes whether the message is loved or not:
We're declating new variable
iconImagePath and assigning string
./images/ to it - that's the first part of our file path.
The second part depends on whether the message is loved or not. We're using conditional operator in our expression:
Which is a short-hand for
Our image file path string depends on the value of
props.isLoved which is passed to
Message component from a parent
statelessFunctionComponentClass function returns JSX code that will be rendered when we render our
span elements nested inside of
span element. The text for our message comes as a propety for
As you can see our
Message component doesn't know in advance about what text and which image it's going to render. Those decisions will be made by
MessageContainer component and passed as properties to
And that's how a parent component can communicate with a child component in React.
MessageContainer component next:
As we discussed previously, our
MessageContainer component is going to stateful, because we want it to maintain our application's state.
getInitialState function that returns the initial state object with a single property
isLoved set to
isLoved property tracks whether user loved message or not. Initially - it's not loved.
Let's take a look at what
MessageContainer component renders:
'Now you know how React.js components communicate with each other.' string to
messageText variable and then we're rendering a new instance of
Message component instance receives 2 properties: 1)
text property that tells which message text we want to render and 2)
isLoved property which tells whether this message is loved or not. The value for
isLoved property is coming from
MessageContainer component's state:
At this point, we've created
MessageContainer component that knows whether message is loved or not and renders
Message component by passing a couple of properties to it.
Next we need to render our
Let's create our
Just like with
Message component we're using function to create React component class.
Button component will render
<button> element with a text that comes from a parent component via
We also want our button to react on user click. To achieve that we create
onClick property and assign
props.onClick to it.
props.onClick references a function that our parent
MessageContainer component passes as a property when it creates a new instance of our
And that's all we need to do to create
Button component class.
Now let's render a new instance of
Button component inside of
We import our
Button component class first. Then we render a new instance of it right after our
Message component instance.
text property on our
Button component instance. The value for this property will be either
'Love' - it depends on what is the value of
As you can see we're using conditional
? operator here too.
isLoved is set to
false, so our
Button component is going to render
Love text and our
Message component is going to render icon.
And now the key question: when user clicks our button how can
Button component change state of
MessageContainer component? In other words: in React how a child component can communicate with a parent component?
We've already seen in this tutorial how a parent component can communicate with a child component via properties and
props object. But what about the other way around?
The answer is: a callback function. A parent component can pass a reference to a callback function (as a property) that a child component can call (and pass arguments if needed).
Let's create a new property
toggleLove on our
MessageContainer component's specification object that references a function:
This function will change component's state by calling
this.setState function and setting the value of
isLoved property to the opposite of the current value:
Where and when do we want to call our new
toggleLove function? In our
Button component when user clicks on our button!
Let's pass a reference to
toggleLove function as a value to
onClick property on our
Button component instance:
Now when user clicks on our
<button> element React will call
props.onClick which references
this.toggleLove function. Which in turn will change
MessageContainer component's state and re-render
Button components, passing new properties to them.
Effectively toggling from to and switching from
'Love' text to
'Unlove' button text.
And that's how a child component can communicate with a parent component in React.
Here is our complete
Thank you for your attention!