Coder Social home page Coder Social logo

redux's Introduction

Redux

Why is this important?

This workshop is important because:

Keeping track of an application's state is hard. Redux's patterns help our data stay in sync when our users take asynchronous actions.

What are the objectives?

After this workshop, developers will be able to:

  • Illustrate Redux's data-flow
  • Keep track of your application's state with a store
  • Define and emit actions to update your state
  • Calculate diffs to your state with reducers
  • Integrate Redux into a React component

Where should we be now?

Before this workshop, developers should already be able to:

  • Write JavaScript
  • Build a simple application with React

Philosophy

Redux's main purpose is to manage the state of an application. Its patterns are expressly inspired by Flux, Facebook's recommended way to manage state among React components and Elm, a functional programming language.

Three Principles

Redux has three very important design choices:

  • Single source of truth: The entire state of your application is stored as an object within your application's store. More specifically this object is a state tree, an object that contains other objects, representing the application's state.
  • State is read-only: The only way to mutate your application's state is to emit an action and create a new state object. All actions are dispatched to a centralized location, which helps make your state easier to keep track of.
  • Changes are made with pure functions: Changes to your state are determined by reducers, which are pure functions that take in the previous state and an action. Using this information, it determines the updated state. Your application may start with a single reducer, but as the application grows, different reducers can manage different parts of the application's state.

Redux Architecture

redux-architecture

Redux Like Button

Let's take a look at implementing a simple like button to see how actions, reducers, and a store may work together to maintain state.

In starter-code run npm install to install all the dependencies and get your gulp task running. In a separate tab run npm start to get your server started on port 3000.

First, let's create a like button in our index.html in addition to a place where we can see the total likes. Giving them both ids will help us reference them later.

<h3 id="total-likes"></h3>
<button id="like-button">Like</button>

Now in our index.jsx (we'll use actual JSX later) let's select these elements.

const likeButton = document.getElementById("like-button")
const totalLikes = document.getElementById("total-likes")

Now we're going to create a reducer, which we'll later register with a store and start dispatching actions to it!

const likes = (state = 0, action) => {
  switch(action.type) {
    case 'LIKE':
      return state + 1
    default:
      return state
  }
}

The above store's state defaults to 0. If it is passed an action of type "LIKE", then it increments its state by 1. Otherwise it does nothing.

Now, using this reducer, we can create a store for our application. At the top of our file, let's import Redux.

import { createStore } from 'redux'

What is this syntax? It's how we import a specific member (distinct piece) of the Redux module (library).

Note: If you do want to import everything that can be done with the syntax, import * as Redux from 'redux'. Then you could access its createStore member with Redux.createStore. However, we're going to prefer the above syntax.

Now let's use Redux's createStore method to create a store for our application. This store will contain the applications state and know how to update it appropriately because we will give it our reducer.

// create a store, where the state lives
const store = createStore(likes);

Now we can get our application's state at any time by calling store.getState(). We know we're going to want the number of likes in our store reflected on the section of our html page, #total-likes. To display the current state to our user, we'll have to update the view everytime the state changes. It will be helpful to have a function that can do this for us.

// update the DOM with the new state
const renderView = () => {
  totalLikes.innerText = store.getState();
}

Everytime this function is run it will update our view to display the latest state.

How many times is renderView being called at the moment? None. Let's call it once so that on page load the initial state is shown as being 0, which our reducer has defined for us in the line: const likes = (state = 0, action) => {...}.

// called once for initialization
renderView()

But how does the view know to update (render) when changes to the store are made? It doesn't. Because of that, we have to subscribe functions to the store. Any function that is subscribed to the store will get run any time the store is updated. Nifty!

// re-render every time the store is updated
store.subscribe(renderView)

Lastly we need to dispatch a "LIKE" event to our reducer when the user clicks the #like-button.

// make the like button dispatch a "LIKE" action
likeButton.addEventListener('click', () => {
  store.dispatch({type: 'LIKE'})
})

Try it out!

Example Code
"use strict"
import {createStore} from 'redux'
const likeButton = document.getElementById("like-button")
const totalLikes = document.getElementById("total-likes")

// reducer for the like button
const likes = (state = 0, action) => {
  switch(action.type) {
    case 'LIKE':
      return state + 1
    case 'DISLIKE':
      return state - 1
    default:
      return state
  }
}

// create a store, where the state lives
const store = createStore(likes);

// update the DOM with the new state
const renderView = () => {
  totalLikes.innerText = store.getState();
}

// re-render every time the store is updated
store.subscribe(renderView)

// called once for initialization
renderView()

// make the like button dispatch an action
likeButton.addEventListener('click', () => {
  store.dispatch({type: 'LIKE'})
})

Challenge: Dislike!

On your own create a dislike button that trigger a DISLIKE action and decrements the state by 1 each time it is clicked.

In other words, update the reducer to include a new "DISLIKE" action type that decrements the state by 1.

Then, make a dislike button.

Then, target the button.

Finally, add an event listener to your dislike button that triggers a DISLIKE action.

Integrating React

Let's refactor our JavaScript by introducing a React component called LikeCounter. First, comment out any code that's concerned with updating our view as we'll use React to take care of it.

Let's create a LikeCounter component in index.jsx:

const LikeCounter = React.createClass({
  like() {
    store.dispatch({type: 'LIKE'})
  },
  render() {
    return (
      <div>
        <h3>{store.getState()}</h3>
        <button onClick={this.like}>Like</button>
      </div>
    )
  }
})

This component will get passed the likeCount as a prop. Additionally it has a function like that when triggered dispatches a LIKE action to our reducer.

Now our renderView function can get updated to re-render our react component and pass our store's state into it as a prop, likeCount.

const renderView = () => {
  ReactDOM.render(
    <LikeCounter/>,
    document.getElementById("like-counter")
  )
}

Don't forget to make a place on your HTML page for the component to live.

<div id="like-counter"></div>

Then clear out all the older HTML elements (buttons and the total-likes heading).

Also, just like before, ensure that renderView gets called once initially and is also called anytime the state is updated.

// render every time the store is updated
store.subscribe(renderView)

// called once for initialization
renderView();

Challenge: Dislike it again!

Make a dislike method for your LikeCounter component that dispatches a 'DISLIKE' action when the dislike button is clicked.

First, add the Dislike button. Then, have a look at where the {{this.like}} function is. Put the dislike() function in the same place.

Helpful Redux Middleware & Complementary Modules

Note: Redux has middleware for it, to extend its behavior.

More Videos & Blog Posts

Final Questions

What are Redux's: Three Priciples?
  • The entire state of your application is stored in a single object.
  • This object is never mutated but instead used to create a state object each time an action is taken.
  • Reducers are pure functions, meaning that provided with a specific input they will always return an expected output.
What is the Purpose of a Reducer?

A reducer takes in an original state and an action type to decide what the updated state of the application will become.

Why do Redux and React play well together? Can you use Redux with other client-side frameworks?

React displays the state (view), while Redux manages the state (model) of the application.

redux's People

Contributors

ilias-t avatar zebgirouard avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.