Summarizing data flow of Redux

Tomoharu Tsutsumi
5 min readMay 26, 2019

I began to study Redux. It is a framework of React like you know. When I used it for the first time, I thought the structure was so complicated. Especially, I couldn’t understand the data flow. Finally I know the flow, so I summarize it.

Before starting

I give the figure of the data flow. I will tell each below.

When you see this figure, please pay attention to the first step. It is Component. A user put his or her data into input field in Component. After that, data flow begins.

The goal

The function I want to implement is below.

The function to post

You can write text in the text field and when you push, the contents are displayed.

Okay, I will show you parts which make redux.

Component

Before studying Redux, we must know React. Component is the range of React. Component is the display users can see. Therefore, it takes charge of UI. The example is below.

I use two components in this article.

First one is todo.js

/* todo.js */import React from 'react'import PropTypes from 'prop-types'  const Todo = ({text}) => (     <li>       {text}     </li>  )  Todo.propTypes =  {    text: PropTypes.string.isRequired  }export default Todo

Second one is todolist.js

/*todolist.js*/
import React from 'react'
import PropTypes from 'prop-types'import Todo from './todo'const TodoList = ({ todos }) => ( <ul> {todos.map((todo) => <Todo key={todo.id} {...todo} /> )} </ul>)export default TodoList

These are not difficult. todo.js is in charge of displaying listed todos. todolist.js wraps todo.js.

Container

Actually, container is a kind of component. Container’s role is …

・Display UI

・Connect Component with Store

I will tell you about “Store” Anyway I show the example. There are two Containers.

First one is Addtodo.js

/* Addtodo.js */
import React from 'react'
import { connect } from 'react-redux'import { add } from '../actions'let AddTodo = ({dispatch}) => { let input return ( <div> <input ref={(node) => { input = node }} /> <button onClick={() => { dispatch(add(input.value)) input.value = '' }}> Add Todo </button> </div> )}AddTodo = connect()(AddTodo)export default AddTodo

Second one is VisibleTodoList.js

/*VisibleTodoList.js*/import { connect } from 'react-redux'import TodoList from '../components/todolist'const mapStateToProps = (state) => {   return {todos: state.todos}}const VisibleTodoList = connect(   mapStateToProps)(TodoList)export default VisibleTodoList

There are two arguments. They are dispatch and state. You can use “state” and “dispatch” in the containers by writing the codes. Those Containers have an opposite role. Addtodo.js’s role is sending user input data to store. Conversely, VisibleTodoList’s role is sending data from store to component. I have already told you that Container is connecting Component with Store. This is it. In AddTodo.js, when user pushes “add todo”, dispatch method send the input data. Moreover Addtodo.js is in charge of Component too. Connect method is make the connection AddTodo Component (const AddTodo) with Store. In VisibleTodoList, Connection Todolist.js with store is made. mapStateToProps is sending the data from store to Component. In this case, This method names state.todos todos. Component gets the data as todos.You can see variable “todos” in todolist.js. This means todolist.js gets data “todos” from VisibleTodoList.js.

Action Creator

This is like routing and decides what redux does when user input something. I show the example.

/* actions/index.js */ 
let nextid = 0
export const add = (text) =>{ return { type: 'ADD', id: nextid++, text } }

Do you remember “dispatch(add(input.value))” in Addtodo.js? That is this. “dispatch(add(input.value))” means sending data to store by using add action. The structure of ActionCreator is decided. It includes property “type”. Action creator judges what to do by confirming the type. The name of type is not decided, but many people use uppercase because it is const. In this case, I added id, text. When you use ul tag and li tag in React, li tag must have “key id”. To deal with it, the property “id” is added. And, The most important property “text” has the text value user wrote. Action Creator creates action. The structure of action is below. If a user write “hello” in the text field,

{type: "ADD", id: 1, text: "hello"}

this action is made. You can think this action as the order to Redux.

Reducer

Reducer’s role is changing state in Store. Reducer gets the orders from Action creator and change states. The example is below.

/* reducers/index.js */import { stat } from "fs";const todo = (state, action) =>{  switch (action.type) {    case 'ADD':      return {        id: action.id,        text: action.text      }   default:     return state  }}const todos = (state = [], action) => {  switch (action.type) {    case 'ADD':      return [        ...state,        todo(undefined, action)      ]    default:      return state  }}export default todos;

I tell “const todos” first. This gets actions from actions creators and sends the datas to “const todo”. If action’s type is “add”, case “ADD” is executed. However, Action creator doesn’t send anything, “default:” is executed. And “const todo” returns new state. The state has id and text if the action’s type is “ADD”. The states in Store are changed by using this information. Reducers don’t update state, create new state. You must pay attention.

*Combine Reducers

This is an added function of reducers. Basically, Your system becomes more complex. There are many kinds of states. They should be organized. In that case, “Combine Reducers” is useful. The example is below.

import { combineReducers } from 'redux'import todos from './todo'const todoApp = combineReducers({ todos })export default todoApp

By writing above, you can wrap todo by “todos”. And wrapped hash is todoApp.

Store

Store has datas of state. One project has only one Store. You must make Store by writing codes below.

/* src/index.js */import React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';import * as serviceWorker from './serviceWorker';import { Provider } from 'react-redux'import { createStore } from 'redux'import todo from './reducers'import { add } from './actions/index'import todoApp from './reducers/index'const store = createStore(todoApp)ReactDOM.render(  <Provider store = {store}>    <App />  </Provider>,  document.getElementById('root'));

When you make Store, you must select reducers. In this case, that is “todoApp”. Components can connect Store because Provider wraps all the Components. The inside of App Component is below.

import React from 'react';import logo from './logo.svg';import './App.css';import AddTodo from './containers/Addtodo'import VisibleTodoList from './containers/VisibleTodoList'class App extends React.Component{  render(){    return(      <div>        <AddTodo />        <VisibleTodoList />      </div>    )  }}export default App;

AddTodo and VisibleTodoList are here. You remember they are containers and get datas of states from stores.

Wrap up

This data flow is complex a bit. However, when you chase the flow carefully, you can understand it.

If you think this article good, please follow me!

https://twitter.com/tomoharutsutsum

--

--

Tomoharu Tsutsumi

Senior Software Engineer at two industry-leading startups ( Go | Ruby | TypeScript | JavaScript | Gin | Echo | Rails | React | Redux | Next)