Menu Search
Jump to the content X X
Smashing Conf Barcelona 2016

We use ad-blockers as well, you know. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

An Introduction To Redux

Redux1 is one of the hottest libraries in front-end development these days. However, many people are confused about what it is and what its benefits are.

As the documentation2 states, Redux is a predictable state container for JavaScript apps. To rephrase that, it’s an application data-flow architecture, rather than a traditional library or a framework like Underscore.js and AngularJS.

Redux was created by Dan Abramov around June 2015. It was inspired by Facebook’s Flux and functional programming language Elm. Redux got popular very quickly because of its simplicity, small size (only 2 KB) and great documentation. If you want to learn how Redux works internally and dive deep into the library, consider checking out Dan’s free course3.

Redux is used mostly for application state management. To summarize it, Redux maintains the state of an entire application in a single immutable state tree (object), which can’t be changed directly. When something changes, a new object is created (using actions and reducers). We’ll go over the core concepts in detail below.

How Is It Different From MVC And Flux? Link

To give some perspective, let’s take the classic model-view-controller (MVC) pattern, since most developers are familiar with it. In MVC architecture, there is a clear separation between data (model), presentation (view) and logic (controller). There is one issue with this, especially in large-scale applications: The flow of data is bidirectional4. This means that one change (a user input or API response) can affect the state of an application in many places in the code — for example, two-way data binding. That can be hard to maintain and debug.

Flux is very similar to Redux. The main difference is that Flux has multiple stores that change the state of the application, and it broadcasts these changes as events. Components can subscribe to these events to sync with the current state. Redux doesn’t have a dispatcher, which in Flux is used to broadcast payloads to registered callbacks. Another difference in Flux is that many5 varieties are available, and that creates some confusion and inconsistency.

Benefits Of Redux Link

You may be asking, “Why would I need to use Redux?” Great question. There are a few benefits of using Redux in your next application:

  • Predictability of outcome
    There is always one source of truth, the store, with no confusion about how to sync the current state with actions and other parts of the application.
  • Maintainability
    Having a predictable outcome and strict structure makes the code easier to maintain.
  • Organization
    Redux is stricter about how code should be organized, which makes code more consistent and easier for a team to work with.
  • Server rendering
    This is very useful, especially for the initial render, making for a better user experience or search engine optimization. Just pass the store created on the server to the client side.
  • Developer tools
    Developers can track everything going on in the app in real time, from actions to state changes.
  • Community and ecosystem
    This is a huge plus whenever you’re learning or using any library or framework. Having a community behind Redux6 makes it even more appealing to use.
  • Ease of testing
    The first rule of writing testable code is to write small functions that do only one thing and that are independent. Redux’s code is mostly functions that are just that: small, pure and isolated.

Functional Programming Link

As mentioned, Redux was built on top of functional programming concepts. Understanding these concepts is very important to understanding how and why Redux works the way it does. Let’s review the fundamental concepts of functional programming:

  • It is able to treat functions as first-class objects.
  • It is able to pass functions as arguments.
  • It is able to control flow using functions, recursions and arrays.
  • It is able to use pure, recursive, higher-order, closure and anonymous functions.
  • It is able to use helper functions, such as map, filter and reduce.
  • It is able to chain functions together.
  • The state doesn’t change (i.e. it’s immutable).
  • The order of code execution is not important.

Functional programming allows us to write cleaner and more modular code. By writing smaller and simpler functions that are isolated in scope and logic, we can make code much easier to test, maintain and debug. Now these smaller functions become reusable code, and that allows you to write less code, and less code is a good thing. The functions can be copied and pasted anywhere without any modification. Functions that are isolated in scope and that perform only one task will depend less on other modules in an app, and this reduced coupling is another benefit of functional programming.

01-functional-programming-opt-preview7
Functional programming example (Image: Tanya Bachuk168) (View large version9)

You will see pure functions, anonymous functions, closures, higher-order functions and method chains, among other things, very often when working with functional JavaScript. Redux uses pure functions heavily, so it’s important to understand what they are.

Pure functions return a new value based on arguments passed to them. They don’t modify existing objects; instead, they return a new one. These functions don’t rely on the state they’re called from, and they return only one and the same result for any provided argument. For this reason, they are very predictable.

Because pure functions don’t modify any values, they don’t have any impact on the scope or any observable side effects, and that means a developer can focus only on the values that the pure function returns.

Where Can Redux Be Used? Link

Most developers associate Redux with React, but it can be used with any other view library. For instance, you can use Redux with AngularJS10, Vue.js, Polymer, Ember, Backbone.js and Meteor. Redux plus React, though, is still the most common combination. Make sure to learn React in the right order: The best guide is Pete Hunt’s11, which is very helpful for developers who are getting started with React and are overwhelmed with everything going on in the ecosystem. JavaScript fatigue12 is a legitimate concern among front-end developers, both new or experienced, so take the time to learn React or Redux the right way in the right order.

One of the reasons Redux is awesome is its ecosystem13. So many articles, tutorials, middleware, tools and boilerplates are available. Personally, I use David Zukowski’s boilerplate14 because it has everything one needs to build a JavaScript application, with React, Redux and React Router. A word of caution: Try not to use boilerplates and starter kits when learning new frameworks such as React and Redux. It will make it even more confusing, because you won’t understand how everything works together. Learn it first and build a very simple app, ideally as a side project, and then use boilerplates for production apps to save time.

Building Parts Of Redux Link

Redux concepts might sound complicated or fancy, but they’re simple. Remember that the library is only 2 KB. Redux has three building parts: actions, store and reducers.

02-redux-data-flow-opt-preview15
Redux data flow (Image: Tanya Bachuk168) (View large version17)

Let’s discuss what each does.

Actions Link

In a nutshell, actions are events. Actions send data from the application (user interactions, internal events such as API calls, and form submissions) to the store. The store gets information only from actions. Internal actions are simple JavaScript objects that have a type property (usually constant), describing the type of action and payload of information being sent to the store.

{
	type: LOGIN_FORM_SUBMIT,
	payload: {username: ‘alex’, password: ‘123456’}
}

Actions are created with action creators. That sounds obvious, I know. They are just functions that return actions.

function authUser(form) {
	return {
		type: LOGIN_FORM_SUBMIT,
		payload: form
	}
}

Calling actions anywhere in the app, then, is very easy. Use the dispatch method, like so:

dispatch(authUser(form));

Reducers Link

We’ve already discussed what a reducer is in functional JavaScript. It’s based on the array reduce method, where it accepts a callback (reducer) and lets you get a single value out of multiple values, sums of integers, or an accumulation of streams of values. In Redux, reducers are functions (pure) that take the current state of the application and an action and then return a new state. Understanding how reducers work is important because they perform most of the work. Here is a very simple reducer that takes the current state and an action as arguments and then returns the next state:

function handleAuth(state, action) {
	return _.assign({}, state, {
		auth: action.payload
	});
}

For more complex apps, using the combineReducers() utility provided by Redux is possible (indeed, recommended). It combines all of the reducers in the app into a single index reducer. Every reducer is responsible for its own part of the app’s state, and the state parameter is different for every reducer. The combineReducers() utility makes the file structure much easier to maintain.

If an object (state) changes only some values, Redux creates a new object, the values that didn’t change will refer to the old object and only new values will be created. That’s great for performance. To make it even more efficient you can add Immutable.js18.

const rootReducer = combineReducers({
	handleAuth: handleAuth,
	editProfile: editProfile,
	changePassword: changePassword
});

Store Link

Store is the object that holds the application state and provides a few helper methods to access the state, dispatch actions and register listeners. The entire state is represented by a single store. Any action returns a new state via reducers. That makes Redux very simple and predictable.

	import { createStore } from ‘redux’;
	let store = createStore(rootReducer);
	let authInfo = {username: ‘alex’, password: ‘123456’};
	store.dispatch(authUser(authInfo));

Developer Tools, Time Travel And Hot Reloading Link

To make Redux easier to work with, especially when working with a large-scale application, I recommend using Redux DevTools19. It’s incredibly helpful, showing the state’s changes over time, real-time changes, actions, and the current state. This saves you time and effort by avoiding console.log’s current state and actions

03-redux-dev-tools-opt-preview20
Redux DevTools (View large version21)

Redux has a slightly different implementation of time travel than Flux. In Redux, you can go back to a previous state and even take your state in a different direction from that point on. Redux DevTools supports the following “time travel”22 features in the Redux workflow (think of them as Git commands for your state):

  • Reset: resets to the state your store was created with
  • Revert: goes back to the last committed state
  • Sweep: removes all disabled actions that you might have fired by mistake
  • Commit: makes the current state the initial state

The time-travel feature is not efficient in production and is only intended for development and debugging. The same goes for DevTools.

Redux makes testing much easier because it uses functional JavaScript as a base, and small independent functions are easy to test. So, if you need to change something in your state tree, import only one reducer that is responsible for that state, and test it in isolation.

Build An App Link

To conclude this introductory guide, let’s build a very simple application using Redux and React. To make it easier for everyone to follow, I will stick to plain old JavaScript, using ECMAScript 2015 and 2016 as little as possible. We’ll continue the log-in logic started earlier in this post. This example doesn’t use any live data, because the purpose of this app is to show how Redux manages the state of a very simple app. We’ll use CodePen.

1. React Component Link

We need some React components and data. Let’s make a simple component and render it on the page. The component will have an input field and a button (it’s a very simple log-in form). Below, we’ll add text that represents our state:

See the Pen Intro to Redux23 by Alex Bachuk (@abachuk3633302724) on CodePen3734312825.

2. Events and Actions Link

Let’s add Redux to the project and handle the onClick event for the button. As soon as the user logs in, we will dispatch the action with the type LOGIN and the value of the current user. Before we can do that, we have to create a store and pass a reducer function to it as an argument. For now, the reducer will just be an empty function:

See the Pen Intro to Redux – Step 2. Events and Actions26 by Alex Bachuk (@abachuk3633302724) on CodePen3734312825.

3. Reducers Link

Now that we have the action firing, the reducer will take that action and return a new state. Let’s handle the LOGIN action returning a logged-in status and also add a LOGOUT action, so that we can use it later. The auth reducer accepts two parameters:

  1. the current state (which has the default value),
  2. the action.

See the Pen Intro to Redux – Step 3. Reducers29 by Alex Bachuk (@abachuk3633302724) on CodePen3734312825.

4. Displaying the Current State Link

Now, that we have the initial state (the default value in reducer) and the React component ready, let’s see how the state looks. A best practice is to push the state down to children components. Because we have only one component, let’s pass the app’s state as a property to auth components. To make everything work together, we have to register the store listener with a subscribe helper method, by wrapping ReactDOM.render in a function and passing it to store.subscribe():

See the Pen Intro to Redux – Step 4. Displaying current state32 by Alex Bachuk (@abachuk3633302724) on CodePen3734312825.

5. Log In and Out Link

Now that we have log-in and log-out action handlers, let’s add a log-out button and dispatch the LOGOUT action. The last step is to manage which button to display log-in or log-out by moving this log-in outside of the render method and rendering the variable down below:

See the Pen Intro to Redux – Step 5. Login/Logout35 by Alex Bachuk (@abachuk3633302724) on CodePen3734312825.

Conclusion Link

Redux is gaining traction every day. It’s been used by many companies38 (Uber, Khan Academy, Twitter) and in many projects (Apollo39, WordPress’ Calypso40), successfully in production. Some developers might complain that there is a lot of overhead. In most cases, more code is required to perform simple actions like button clicks or simple UI changes. Redux isn’t a perfect fit for everything. There has to be a balance. Perhaps simple actions and UI changes don’t have to be a part of the Redux store and can be maintained at the component level.

Even though Redux might not be ideal solution for your app or framework, I highly recommend checking it out, especially for React applications.

Front page image credits: Lynn Fisher, @lynnandtonic41

(rb, vf, al, il)

Footnotes Link

  1. 1 https://github.com/reactjs/redux
  2. 2 http://redux.js.org/
  3. 3 https://egghead.io/series/getting-started-with-redux
  4. 4 http://stackoverflow.com/questions/33447710/mvc-vs-flux-bidirectional-vs-unidirectional
  5. 5 https://github.com/kriasoft/react-starter-kit/issues/22
  6. 6 https://github.com/xgrommx/awesome-redux
  7. 7 https://www.smashingmagazine.com/wp-content/uploads/2016/06/01-functional-programming-opt.png
  8. 8 http://tanyabachuk.com
  9. 9 https://www.smashingmagazine.com/wp-content/uploads/2016/06/01-functional-programming-opt.png
  10. 10 https://www.npmjs.com/package/ng-redux
  11. 11 https://github.com/petehunt/react-howto
  12. 12 https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4#.ggnvvy40d
  13. 13 https://github.com/xgrommx/awesome-redux
  14. 14 https://github.com/davezuko/react-redux-starter-kit
  15. 15 https://www.smashingmagazine.com/wp-content/uploads/2016/06/new-redux-data-flow-large-opt.png
  16. 16 http://tanyabachuk.com
  17. 17 https://www.smashingmagazine.com/wp-content/uploads/2016/06/new-redux-data-flow-large-opt.png
  18. 18 https://facebook.github.io/immutable-js/
  19. 19 https://github.com/gaearon/redux-devtools
  20. 20 https://www.smashingmagazine.com/wp-content/uploads/2016/06/03-redux-dev-tools-opt.png
  21. 21 https://www.smashingmagazine.com/wp-content/uploads/2016/06/03-redux-dev-tools-opt.png
  22. 22 https://github.com/gaearon/redux-devtools-log-monitor/blob/master/README.md#features
  23. 23 'http://codepen.io/abachuk/pen/Meaxgm/'
  24. 24 'http://codepen.io/abachuk'
  25. 25 'http://codepen.io'
  26. 26 'http://codepen.io/abachuk/pen/yJYwYX/'
  27. 27 'http://codepen.io/abachuk'
  28. 28 'http://codepen.io'
  29. 29 'http://codepen.io/abachuk/pen/LZpaGX/'
  30. 30 'http://codepen.io/abachuk'
  31. 31 'http://codepen.io'
  32. 32 'http://codepen.io/abachuk/pen/NrGJRR/'
  33. 33 'http://codepen.io/abachuk'
  34. 34 'http://codepen.io'
  35. 35 'http://codepen.io/abachuk/pen/dXYrpr/'
  36. 36 'http://codepen.io/abachuk'
  37. 37 'http://codepen.io'
  38. 38 https://github.com/reactjs/redux/issues/310
  39. 39 https://github.com/apollostack/apollo-client
  40. 40 https://github.com/Automattic/wp-calypso
  41. 41 https://twitter.com/lynnandtonic
SmashingConf Barcelona 2016

Hold on, Tiger! Thank you for reading the article. Did you know that we also publish printed books and run friendly conferences – crafted for pros like you? Like SmashingConf Barcelona, on October 25–26, with smart design patterns and front-end techniques.

↑ Back to top Tweet itShare on Facebook

Advertisement

Alex is a front-end developer who specializes in JavaScript development. He's developed anything from WordPress websites to complex e-commerce JavaScript applications. Alex writes about web development on his blog and sometimes contributes to open-source projects. He is a co-founder of educational platform ClassMate.io. Alex spends his free time with with his familiy in Fairfield, CT., helps organizing JavaScript meetups and conferences and likes to bike around NYC.

Twitter: Follow Alex Bachuk on Twitter

  1. 1

    Just a note: is it a typo or I didn’t understand it correctly or I am wrong:
    Regarding pure functions, you say – “These functions don’t rely on the state they’re called from, and they return only one and the same result for any provided argument.”

    Shouldn’t they always return the same result given same parameters, not the same result given any provided parameter?

    Other than that, great article, I really enjoyed reading it.

    8
    • 2

      Alex Bachuk

      June 28, 2016 4:21 pm

      Pure functions don’t depend on external state and that’s why they always return only one and the same result. That’s what makes them more predictable and easy to test.
      Impure function, on the other hand, can return different results based on other factors like external state or non-local variables, that are outside of that function.

      -5
      • 3

        Your sure if you are not a native english speaker or you just have some problem expressing yourself clearly, but pure functions don’t return “only one and the same result”: the return the same result for the same given parameters.

        You might have that in mind all along, but it’s misleading to state it like you did and leave it implied.

        -5
        • 4

          Damn smartphone typing…

          It should be:

          NOT sure if you are not a native english speaker or you just have some problem expressing yourself clearly, but pure functions don’t return “only one and the same result”: THEY return the same result for the same given parameters.

          0
          • 5

            I am a native English speaker, and I took “they return only one and the same result for any provided argument” to mean that any given input can have only one possible output. The wording is a little clumsy, because for one thing a function may have multiple arguments, but I would never have interpreted that as meaning that the function has a single, fixed result regardless of what input it receives.

            1
      • 6

        Pure functions return the same result given the same arguments and don’t depend on any state. You have it written like pure functions return the same result given any argument which is wrong.

        0
  2. 7

    Pablo Sanfilippo

    June 28, 2016 2:09 pm

    I’ve been using it in my latest projects alongside with redux-saga. Working great so far.

    2
  3. 8

    Learnt more about redux than I have reading articles on the web. This was a great start and a good read, thanks for sharing.

    1
  4. 9

    Vinícius Alves Oyama

    July 2, 2016 3:05 am

    There is one thing that I cannot understand on this whole flow and I’ve got a question:

    What to do with the global state when route changes in a web app? Should I set a new empty state and save the old? So when the user go back I can restaure it?

    Suppose we have an app with 2 routes:

    /users
    /approved-users

    When I go to /users there is a trigger “before view load” or something like that to dispatch an action to load the users. Then some reducer sets the key “users” on the global state with [ {..user1..}, {..user2..}, …] and the view shows it.
    Then I click on approved users menu. Another event is dispatched: “load_approved_users” and another reducer sets THE SAME KEY “users” with another array [ {..anotheruser1..}, {..anotheruser2..}, …] .

    If I the user go back the state will have incorrect users unless I restore the previous state. I have not worked with Redux/React but I’ve worked with some libraries to use redux with Angular/Angular2 and Aurelia and none of them deal with this situation.

    Another problem is: if we do not empty the state when the route change, the users array will have the old users until the load_approved_users event load the new. So de view will show invalid records.

    Is there some concept that I’m missing here?

    0
    • 10

      You can redux this to separate store sections by calling corresponding actions for users and approved-users. Another way to do is to replace previous results and then request new state with page change.

      I combine this methods for now, because i build my first app and don’t know how to do it right. App for api with server pagination and filtering with react+redux+normalizr based on real-world redux example. Initially, in componentDidMount() i request first page of api results and save to store:

      state: {
        page: {
          1: {...}
        }
      }
      

      When click on pagination, request from api and merge corresponding page to state. Result state for visited page 1 and 3:

      state: {
        page: {
          1: {...},
          3: {...},
        }
      }
      

      But when i use filter, before load server filtered results i completely clean page section.

      0
  5. 11

    Fagner Brack

    July 9, 2016 10:29 am

    > Redux is a predictable state container for JavaScript apps. To rephrase that, it’s an application data-flow architecture, rather than a traditional library or a framework like Underscore.js and AngularJS.

    That’s incorrect.

    Redux is just a library, not an architecture, according to Dan Abramov: https://github.com/gaearon/ama/issues/110#issuecomment-230331314

    > It is a JavaScript library: http://redux.js.org/.

    > I am not aware of a design pattern called “Redux”, nor did I reinvent one.
    > I can’t control how people use the library name though.

    Please, stop calling Redux an architecture, you are just helping to increase the confusion and misunderstanding.

    0
  6. 12

    I wanted to learn Redux bit then you started with the whole React demo and i was like “fuck this shit, again React…” and have up. Been doing JavaScript for like 12 years and i still don’t get this redux thing. It must be explained when totally decoupled from other technologies. Create a simple to-do app with jquery and nothing else, and ifc redux.

    1
  7. 13

    Very helpful content! Thanks for sharing Alex!

    1
  8. 14

    The simplest and very helpful tutorial. Thanks for sharing.

    1
  9. 15

    Really great article. Thanks. Using Codepen to demonstrate your code and letting users fiddle with it, is really very helpful.

    1

Leave a Comment

You may use simple HTML to add links or lists to your comment. Also, use <pre><code class="language-*">...</code></pre> to mark up code snippets. We support -js, -markup and -css for comments.

↑ Back to top