Understanding Information Flow in React: Data Down, Action Up

Andy del Valle
The Startup
Published in
7 min readJun 29, 2020
Photo by Samuel Wong on Unsplash

When learning React, you could easily discover the allure of component-based coding and ask yourself why you didn’t make all your previous projects on this high-advantage JavaScript library. Code re-usability, consistency, and maintainability are just a few advantages React components offer. However, when first starting off, understanding the flow of information between components and how to update it can be very frustrating and easily deter someone’s interest.

In this blog, we will first go over what components, state, and props are. Then we’ll go step by step on how information gets passed down for rendering and back up to update information for a DOM re-render.

Components

To start off, we should first recap what a React component is and why mapping them out in a component tree can save you lots of headaches when figuring out the flow of information.

According to the official React documentation:

Components let you split the UI into independent, reusable pieces, and think about each piece in isolation. Conceptually, components are like JavaScript functions. They accept arbitrary inputs (called “props”) and return React elements describing what should appear on the screen.

A website using React components. Image source.

In the Browser image above, each component, distinguished by numbers, is laid out in one single page application. They each have their own functions and contain a section of code that describes what it should render to the DOM. To the right is a UI Tree, also known as a component tree, that helps developers map out parent components, child components, and information flow of properties — props.

State v Props

State

This is information that can be mutated and lives locally in the component in which it is constructed. It can be considered the heart of the component because it is the information that ultimately gets rendered on to the DOM. You can pass down state from parent to child components through props.

Props

This is information that can not be mutated and is passed down from a parent component (information such as state or functions). It is important to note that when information gets passed down from a parent component to a child component, it can not skip “layers” of child components. So with the UI Tree image above, if component 1 wanted to pass down its information, via props, to component 4, it would have to get passed through component 2 first.

“Data down, Action up”

This phrase helps developers understand the flow of information from parent to child component and vice versa.

The first and more simple concept, “data down,” refers to the passing of data and/or functions via props from parent to child components. These props are passed down when a child component gets created. We pass data down to child components so they can render them on to the DOM.

Data is sent down to the child from the parent component with the help of props

Let’s breakdown this “data down” concept into steps:

  1. Parent component creates a child component
  2. Parent component passes down data by referencing this.state via props
  3. Child component can render the data by referencingthis.props

The second and trickier concept to understand, “action up,” refers to sending data back up to the parent from the child component with the help of some action or event. Often these actions are connected to a callback function.

Data is sent back up to the parent from the child component with the help of callback functions

Let’s breakdown this “action up” concept into steps:

  1. A user interacts with a UI element (i.e. click on a button element)
  2. An attached event listener to the UI element is triggered (i.e.onClick)
  3. An attached handler to the event listener is triggered (i.e.handleClick)
  4. A callback function inside the handler is triggered (i.e.onHandleClick)
  5. Logic of the callback function is executed within the parent component
  6. State is updated inside the parent component
  7. Data is sent back down and the DOM re-renders

We’ll go into more detail on each step later with the example below.

Example: Incrementer App

Say we have a simple ‘Incrementer’ app that shows a number on the browser. The user will be able to increment the number by clicking on the button that says “Increment Number by 1.”

Left: Incrementer App on a browser; Right: UI/Component tree

Data Down

Information is passed down from the top-level component called App. Notice that the state includes data(a number with the value 0).

What’s passed down includes:

  • onHandleClick={this.incrementNumber}, a callback function
  • number={this.state.number}

We include them inside the ParentComponent tag. This is referred to as passing down props- “data down.”

ParentComponent receives props from App.

ParentComponent renders a ChildComponent and passes down its props to it.

ChildComponent receives props from ParentComponent

ChildComponent renders the number referencing this.props.number. You can see this on the Incrementer app as the number 0.

Action Up

When the user interacts with the website, they see a button that says “Increment Number by 1.” The user would expect to see the number on screen increment by 1 when they click this button. How does the DOM update the number when the number that is rendered on the screen is a prop, data that can not be mutated? This is where it gets a bit confusing. Data can only be mutated, or updated, where it was created, in state.

In order for the DOM to update, data needs to be sent back up to where it was stored and then back down to where it gets rendered. In other words, data needs to somehow be sent from the child component back to its parent component where state was constructed, update itself, and then go back down to the child component for re-rendering. We can accomplish this through callback props.

In the “Incrementer” example, the data sent down to ChildComponent originated from App. The number: 0 lives in the state of App but gets rendered in the ChildComponent. So when a user clicks on the “Increment number by 1” button, number:0 needs to become number:1 but can only be updated in App.

Let’s perform our “action up” concept to illustrate this.

  1. A user interacts with a UI element. They see “Increment Number by 1” and click on the button.
  2. The attached event listener to the UI element is triggered. You can see inside the button tag isonClick which gets triggered on a mouse click. This then triggers a function insideChildComponent called handleClick. It’s proper naming convention to start any event handler with “handle.” This way you’ll know what this function is actually doing.

3. The attached handler to the event listener is triggered, handleClick

4. The callback function inside the handler is triggered,onHandleClick(). It’s proper naming convention to start any callback function with the word “on” followed by the handler.

5. The logic of the callback function is executed within the parent component. This is seen in the function incrementNumber() below. It takes the previous state number: 0 and increments the value by 1.

6. The state is updated inside the parent component. number: 0 is updated to number: 1

7. Data is sent back down to ChildComponent and re-renders number: 1

Incrementer app with the updated number after DOM re-render

Information flow diagram

Below is a diagram that helps illustrate the information flow with the Incrementer app example:

Diagram of the information flow of Incrementer app

Happy coding! 😊

--

--

Andy del Valle
The Startup

Software Engineer and Full Stack Web Developer based in Seattle, WA