Should I choose Redux or Flux for ReactJS?

Having a similar state, action and unidirectional data flow, the Flux and Redux do have some differences.

An intro to Redux and how state is updated in a Redux application

An intro to Redux and how state is updated in a Redux application

I started learning Redux a few days back and it was an overwhelming concept for me at the start. After polishing my skills in ReactJS by making a&nbsp;<a href="https://github.com/aimenbatool/my-reads" target="_blank">personal book reading application</a>, I headed towards Redux to learn more about it.

I started learning Redux a few days back and it was an overwhelming concept for me at the start. After polishing my skills in ReactJS by making a personal book reading application, I headed towards Redux to learn more about it.

Today, I’m going to share a few core Redux concepts without using any view library (React or Angular). This is a kind of a personal note for future reference but it can help others as well.

Let’s dig in together!

What is Redux?

Redux is an open-source library to improve the predictability of the state in a JavaScript application. It is an independent library. It is commonly used with other libraries like React and Angular for better state management of the application. Redux was created by Dan Abramov in 2015 to handle complex state management in an efficient way.


When an application grows larger it becomes harder to manage the state and debug for issues. It becomes a challenge to track when and where the state is changed and where the changes need to be reflected. Sometimes a user input triggers some API call which updates some model. That model in turn updates some state or maybe the other model and so on.

In such a situation it becomes grinding to track the state changes. It happens mainly because there is no defined rule to update a state and state can be changed from anywhere inside the application.

Redux tries to solve this issue by providing a few simple rules to update the state to keep it predictable. Those rules are the building blocks of Redux.

Redux Store:

As we discussed earlier, the main purpose of Redux is to provide predictable state management in our applications. Redux achieves this by having a single source of truth, that is a single state tree. The state tree is a simple JavaScript object which holds the whole state of our application. There are only a few ways to interact with the state. And this makes it easy for us to debug or track our state.


We now have only one main state which occupies the whole state of the application located at a single location. Any changes made into the state tree are reflected in the whole application because this is the only source of data for the app. And, this is the first fundamental principle of Redux.

Rule #1 — Single source of truth

The state of your whole application is stored in an object tree within a single store. — Official docs

The ways you can interact with a state tree are:

  • Getting the state
  • Listening to the changes in the state
  • Updating the state

store is a single unit that holds the state tree and the methods to interact with the state tree. There is no other way to interact with a state inside the store except through these given methods.

Let’s talk about the methods a store gives us to interact with the state.

  • getState() — Returns the current state of the application.
  • dispatch(action) — The only way to update a state is by dispatching an action and dispatch(action) serves the purpose. We will talk more in detail in a bit.
  • subscribe(listener) — The purpose of this method is to listen for the state changes. Every time a state is changed, it will be called and will return the updated state.
  • replaceReducer(nextReducer) — Replaces the reducer currently used by the store to calculate the state.

Now when we have a store which contains a state tree and a few ways to interact with the state, how can we update application state?

Updating state in the application:

The only way to update a state is to dispatch an action. This is the 2nd rule.


Rule #2 — State is read-only

An action is a plain JavaScript object to keep track of the specific event taking place in the application. What makes it special is a ‘type’ property which is a necessary part of it.


{
  type: "ADD_BOOK_TO_THE_CART"
}

The main purpose of this property is to let Redux know about the event taking place. This type should be descriptive about the action. Along with the ‘type’ property, it can have other information about the event taking place.

Actions can have as much information as you want. It is a good practice to provide less and necessary information — preferably an id or any unique identifier wherever possible.

Here we have an action to add a book to the cart.

{
    type: 'ADD_BOOK_TO_THE_CART',
    bookId: 10, 
}

Once we define our action we pass it to the dispatcher. store.dispatch() is a function provided by the library which accepts an action to perform an action against the state. Redux restricts updating the state to this method only.

store.dispatch({
    type: 'ADD_BOOK_TO_THE_CART',
    bookId: 10,
})

This strict way of updating the state ensures that the state can not be changed directly either by view or any network callback. The only way to update a state is by defining the action and then dispatching it. Remember that actions are plain JavaScript objects. Actions can be logged, serialized, and replayed for debugging purposes.

We now have a store, a state, and an action in our app to perform some tasks against the state. Now we need a way to use these actions to actually do the update. This can be done by using a pure function and this is rule #3.

Rule#3 — Changes are made with pure functions

Magic happens here. We need a simple pure function, which, as a parameter, takes the current state of the application and an action to perform on the state, and then returns the updated state. These functions are called reducers.

function booksReducer (state = [], action) {
// Magic is happening here...
  }

These are called reducers because they take the collection of values, reduce it to an updated state and then return it. Since reducers are pure functions they do not mutate the original state. Instead, they return the updated state in a new object. Our application can have one or more than one reducer. Each reducer can have a relevant state to perform specific tasks.

function booksReducer (state = [], action) {
    switch(action.type) {
        case ADD_BOOK_TO_THE_CART:
            return state.concat([action.bookId]);
        case REMOVE_BOOK_FROM_CART:
            return state.filter( book => book.bookId !== action.bookId);
        // a few more actions
        default:
            return state;
    } 
}

Since reducers are pure functions, they should have the following attributes:

  • Given the same input, it should return the same output every time — No mutation is allowed.
  • No side effects — No API call data change from an external source.

The process.

If we connect the dots, Redux is a library which has a store that contains a state tree and a few methods to interact with the state. The only way to update a state inside a store is to dispatch an action and define a reducer function to perform tasks based on the given actions. Once dispatched, the action goes inside the reducer functions which performs the tasks and return the updated state to the store. This is what Redux is all about.

State update flow in Redux

What have we learned so far?

Let’s summarize what we have learned so far to connect the dots.


  • Redux — An opensource predictable state container
  • State Tree — A plain JavaScript object which contains whole application state
  • Three ways to interact with a state (the only ways):
  • Store — A single unit which contains state tree & methods to interact with the state tree
  • Actions — Plan Javascript objects to describe the action taking place
  • Reducers — Pure Javascript functions to take current state and an action to return a new state

Since Redux is an independent library which can be used with React, Angular or any other library, I avoided making a sample application with any of these view libraries. Instead, I focused on the core Redux concepts only.

Redux can be overwhelming at first and if you are a newbie or junior developer it can give you a tough time. But consistency and a positive attitude is the key to success.

Originally published on https://medium.freecodecamp.org



Redux in React

Redux in React

React Redux is maintained by the Redux team, and kept up-to-date with the latest APIs from Redux and React.

React Redux is maintained by the Redux team, and kept up-to-date with the latest APIs from Redux and React.

React is all about moving parts that pass information to each other. You will notice sometimes you have really long chains that go through several containers and several components. This can be a hassle if the data got messed up in one of the steps and you have to slowly backtrack and look through each part to find the error. there is where Redux comes into play! Redux stores all of your state information in a separate object, and any component can get the information it needs from this object. So instead of going home => container1 => component1=> component2, it will go home => Redux Object => component2. Lets see how this all works!

First is the reducer function.

You have two objects that are separate from everything else, the state and the action. The state contains, well, the state of your page, and the action contains the instructions to update that state.

let state = {name: "abc"}
let action = {type: "JOE-IFY"}

To allow action to modify state, you need a function.

function changeState(state, action) {
   if (action.type === 'JOE-IFY') {
      return {name: 'Joe'}
   }
}

If the action type is ‘JOE-IFY’, change the state of name to be “Joe”. There can be many different commands to change names, typically a switch case it used. However, to make sure a null or undefined is never returned a default case is added that returns the previous state.

function changeState(state, action) {
   switch (action.type) {
      case 'JOE-IFY':
         return {name: 'Joe'}
      default: 
         return: state
   }
}

Now if you ran the changeState function with the state and “JOE-IFY” you would get {name: “Joe”}.

If you had another action type, for example to change the name to “Bob” it would look like:

function changeState(state, action) {
   switch (action.type) {
      case 'JOE-IFY':
         return {name: 'Joe'}
      case 'BOB-IFY':
         return {name: 'Bob'}
      default: 
         return: state
   }
}

Now if you instead ran it with the function “BOB-IFY” you would get {name: “Bob”}. This changeState function is called the “reducer”, as it reduces the state and action into a new state.

You can make it more complicated as well, since an action can have multiple attributes.

let state = {name: "abc"}
let action = {type: "CHANGE_NAME",
              newName: "Spooderman"}

You will have to change the function such that it changes the state of name to that of newName. Something like:

function changeState(state, action) {
   switch (action.type) {
      case 'CHANGE_NAME':
         return {name: action.newName}
      default: 
         return: state
   }
}

This is the gist of how a reducer function works.

Using Redux in a React App

First install redux.

npm install redux

Install react-redux.

npm install react-redux

Inside your “src” folder, create a “reducers” folder, and inside the “reducers” folder create a “reducerFunctionName.js” file.

Redux gives you the createStore() function, which when called returns the state. React-redux gives you the “provider” component, where store is passed in and is subsequently passed down everywhere else. React-redux also lets us re-render whenever the specified changes to the state happen via the connect method. Import them both into index.js. Also import your reducer function.

import {createStore} from 'redux';
import {Provider} from 'react-redux'
import reducerFunctionName from './reducers/reducerFunctionName.js'
const store = createStore(reducerFunctionName);
ReactDom.render(
   <Provider store={store}>
      {' '}
      <App />
   </Provider>, 
   document.getElementById('root')
)

Now we can pass the store and access it in every component. To any component that wishes to access the store, import connect from react-redux and modify the export.

import {connect} from 'react-redux'
const mapStateToProps = state => {
   return {
      name: state.name
   }
}
const mapDispatchToProps = state => {
   return {
      changeName: () => dispatch({type: "CHANGE_NAME"})
   }
}
export default connect(
   mapStateToProps,
   mapDispatchToProps
)(App);

mapDispatchToProps allows us to have access to the “changeName” function, which is what we are calling us passing in action.type “CHANGE_NAME” to the reducer. Similarly, name is provided by the mapStateToProps function, which gives us access to the name in the state.

Your components now have access to the state information inside the store object, and are able to access the functions needed to change the state. Just about done!

One final thing. Now what if you had multiple functions? You can theoretically transform all of them into different cases for the same reducer function, but this would be weird; you would have a case for “CHANGE_NAME”, a case for “BUY_FOOD”, and other cases for tons of weird things that have nothing to do with each other. It is better to separate out the reducer functions. This can be done through “combineReducers”.

In the “reducers” folder create a new file called “rootReducer.js”. At the top enter:

import {combineReducers} from 'redux'

Then copy paste your other reducer functions over, but without the export default part in front of them. Then add it to the end.

export default combinedReducers({
   nameChanger,
   colorChanger
})

Note that now to access information from on of the reducers you have to specify the reducer name first now, so instead of “state.name” if name is stored in the nameChanger function you need to do “state.nameChanger.name”.

Go back to your index.js and import rootReducer from “./reducers/rootReducer.js”, you don’t need the earlier individual file imports anymore.

Your finished combinedReducer should look something like this:

import {combineReducers} from 'redux'
function colorChanger(state = {color: "red"}, action) {
  switch (action.type) {
    case 'CHANGE_COLOR':
      console.log(state);
      return {color: action.newColor}
    default:
      return state;
  }
}
function nameChanger(state = {name: "zed"}, action) {
  switch (action.type) {
    case 'CHANGE_NAME':
      console.log(state);
      return {name: action.newName}
    default:
      return state;
  }
}
export default combineReducers({
  nameChanger,
  colorChanger
})

And an example app.js that uses the above reducers might look something like:

import './App.css';
import React, {Component} from 'react';
import {connect} from 'react-redux';
import Something from './containers/Something.js'
class App extends Component {
handleChange = (event) => {
    this.props.changeName(event.target.value)
  }
handleChange2 = (event) => {
    this.props.changeColor(event.target.value)
  }
render () {
    return (
      <div className="App">
        <form>
          <label>
          NewName: <input type="text" onChange={event => {this.handleChange(event)}}/>
          <br/>
          NewColor: <input type="text" onChange={event => {this.handleChange2(event)}}/>
          </label>
          <br/>
          <input type="submit"/>
        </form>
        <p>{this.props.name}</p>
        <p>{this.props.color}</p>
      </div>
    )
  }
}
const mapStateToProps = state => {
  return {
    name: state.nameChanger.name,
    color: state.colorChanger.color
  };
}
const mapDispatchToProps = dispatch => {
  return {
    changeName: (event) => dispatch({type: 'CHANGE_NAME', newName: event }),
    changeColor: (event) => dispatch({type: 'CHANGE_COLOR', newColor: event })
  };
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

The default states for name and color are shown at the bottom. The redux state for name and color can be updated through the input bars, and the updated state is shown again with the new name and color.

And we are all done! That was a long ride and took me quite a while to figure out, so hopefully this guide helps you learn Redux faster than I did! Happy coding with your newfound knowledge of Redux!

Redux Basics

Redux Basics

In this post, the simplest React Redux tutorial I wish I had when I started learning. ... Having seen the basics let's now talk about what problem Redux tries to solve.

Throughout last week, I had my first taste of Redux. During this time, we implemented Redux with React but, it does not need to be used exclusively with React. However, this has been my only experience with it thus far, so I will explain it the way it is used with React.

Upon introduction to Redux, you may be left feeling instantly confused. Initially learning React, most days are spent getting comfortable with the idea of passing props from one component, to another, to another... to another.... to.... another.

While this is an easy concept to understand, it's not necessarily the most efficient. There are a variety of state management systems used within React, but I want to discuss Redux and what has helped me wrap my mind around it!

You may also like: Angular vs React vs Vue: Which one will be popular in 2020.

What is Redux?

Redux has one main advantage, and that's the efficiency it provides. Redux allows you to store your state in what is called a "Redux Store" and uses actions to call reducers, which in turn manipulate your state however you see fit.

Let's keep this simple and straight to the point. Redux is Uber Eats.

I know what you may be thinking... What are you are talking about? Let me explain.

In traditional prop passing, relate each component to a neighbor. If you needed something from the grocery store, imagine that you have to ask neighbor E, to ask neighbor D, to ask neighbor C, to ask neighbor B, to ask neighbor A, if you can use some of their bread. It works... but, it's pretty inconvenient

What if there was a way to just have the bread delivered straight to you?!

AH, this is where Redux shines. With the use of the Redux store, that bread (AKA state), is always available whenever you need it. No passing props, no talking to neighbors, just simply call up the store and get what you need!

The Redux Store

The Redux Store takes about 3.87 seconds to build, and is one of the easiest things to do in React. After installing Redux with your package manager of choice, simply import the function into your main component (usually index.js).

import { createStore } from 'redux'

Boom! Now you have the power, just create a store really quick! Be sure to export your reducer from it's proper file, and import it into your index.js file.

const store = createStore(yourReducerGoesHere)

Simple enough? Now your store exists in a variable called store. It takes in a reducer as well.(This is how it will manipulate the state that's held within the store. Now, let's talk about the Provider.

Providing state to your components

Provider is simple enough to remember, because it provides access the state from the store to your components. I say access, because it doesn't necessarily give your components the state just yet (this is what we have connect() for).

In that same component, you'll want to import Provider.

import { Provider } from 'react-redux' Booyah!

After that, you want to wrap your App component in that provider. Think of this as granting your application the ability to use the store. It typically looks something like this:

ReactDOM.render(
<Provider store={store}>
    <App />
</Provider>
, document.getElementById("root"));

See that sneaky little prop pass, right there? It almost forms a sentence! In the Provider we passed in the store. It can almost be read as, "Providing the store to the component". Well, that's how I read it at least! :)

Awesome, now we created a store, passed the store to the provider, which is providing that store to our application. Before seeing how we grab the state, we need to have state first! On to the reducer!

Reducing The Stress

Reducers! This is one of the powerful aspects of Redux. Essentially, I call them the execution guidelines. The reducer file will typically consist of two things: the initial state, and the reducer itself.

For example, for simplicity sake, let's say our initial state has an array of names.

const initialState = {
   names: ['Bob', 'Susan']
}

Woo! They are looking great. Now the reducer comes into play. This section can get messy, so we'll keep it extremely simple. Reducers are functions full of if...else conditions. The easier way to write this is with switch cases. To prevent confusion, I'll provide an example of both, if...else and a switch case, if you happen to be familiar with both!

Our case that modifies state will be called, 'Add Name'. However, in Redux cases, it's common practice to use all capital letters for this (kind of similar to just screaming at the reducer to do its job), so it would look like 'ADD_NAME'.

If none of the cases do match, you want to be sure to return the initialState. I know this is a lot of words, so let's see an example!

export const reducer = (state = initialState, action) {
    if (action.type === 'ADD_NAME') {
        return {
            ...state,
            names: [...names, action.payload]
        }
    } else {
        return state
    }
}

What's happening here is the reducer takes in state, and an action. State will be undefined if you don't provide it an initial state, so in this example, we assign state to initialState. The action will be an object containing a type and sometimes a payload property. For example, this action object for this example may look like:

{ type: 'ADD_NAME', payload: newNameGoesHere }

The type specifies what reducer case to trigger, like instructions! The payload is just data, it can be called anything. In this case, we have a new name we want to add to the users array. So we spread the whole state object first, then spread the users array into a new array, and add the new name on to the end, this name is being referenced by the action.payload.

So back to my point, reducers are the execution guidelines. They take instruction from the action, and perform based on what action.type is called. This will make more sense in a second when we discuss actions. The payload property is just a common way of passing in the data you want to incorporate into state, it can be called anything - beanChili if you want! :D

Like I said, reducers are typically written in a switch case format, so they may look like this when you come across them:

export const reducer = (state = initialState, action) {
    switch(action.type){
        case 'ADD_NAME':
            return {
                ...state,
                names: [...names, action.payload]
            }
        default:
            return state
    }
}

This achieves the same result, just tends to be less words, the longer your code gets!

Okay, so we've covered the store, the provider, initial state, and the reducer. Now let's take a peek at actions!

Lights, Camera, ACTIONS

As I stated earlier, actions are the instructions for the reducer. Action creators are functions, that return actions. These actions are objects similar to the one I referenced above, with a type and a payload property.

The way these work, is your action creator function is called within your component, which returns an object of "instructions". In this case, you call the action, and it will return an object that looks like:

{ type: 'ADD_NAME', payload: newName }

This function could be represented by:

export const addName = (newName) => {
   return { type: 'ADD_NAME', payload: newName }
}

In this case, when the addName function is invoked, we will pass in the name we want to add, as newName!

Now, this returned object gets passed into the reducer. Can you tell what's going to happen?

The reducer enters the switch case, and checks the action.type. OH! The type is 'ADD_NAME', so hop into that return statement.

Okay, so it is returning state, and then attaching action.payload onto the enter of the array... what is action.payload?

Well, referencing our object above, we see action.payload is the newName. Let's say that we passed in the name 'Chris' as the newName argument. What happens now, is Chris is tacked onto the end of the array. Now our users array in state looks like:

['Bob', 'Susan', 'Chris'] Awesome!

So essentially we just called a function (an action creator), which said, "Hey Reducer... add a new name, the new name is Chris!"

The reducer responds, "Cool, added the name, here's your new state!"

Simple enough, right? They definitely get more complex as more functionality is incorporated into your application, but these are the basics.

However, there is one final question:

How do the components actually access this state?

Simple! By connect! Let's take a look.

Connecting the links

Connecting the store state to our components becomes a bit of extra work, but essentially we have our state, and provide access to the main component (App.js). However, now we need to accept access, via the connect() method.

Connect is a higher-order component, which is a different topic itself, but essentially this gets invoked twice in a row. It is called during the export of your component.

First, let's import connect into our component:

import { connect } from 'react-redux';

Say we have a <List /> component being rendered in App.js, and we want to connect List.js. In that component, on the export line we could do something like:

export default connect(null, {})(List);

The first invocation takes in two items, the state you're receiving, and the actions you want to use (in that order). Let's touch on the state.

Remember, connecting only accepts access, it doesn't actually provide the state, that's what we have mapStateToProps for. :D

mapStateToProps says, "Oh, you connected your component? You granted access? Well here is the state you asked for!"

Okay... Maybe the component doesn't talk, but if they did, they'd probably say something along those lines.

This mapStateToProps example, is a function that receives the state, and is then passed into the connect method. Like this:

const mapStateToProps = state => {
   return {
      names: state.names 
   }
}

This function takes in state, which is the entire state object from the reducer. In this case, our state object only has one array inside of it, but these state objects are typically 10x as long, so we have to specify what information we want!

In this return line, we say, "Return an object with a names property." How do we know what names is? Well, we access it off of the state object, by state.names.

Our returned property doesn't need to be called names, we could do something like:

const mapStateToProps = state => {
   return {
      gummyBears: state.names
   }
}

But, that's not very semantic is it? We want to understand that names is an array of names. So it's common practice to keep the same property name, in your returned state object!

We're almost finished, so hang in there! Let's recap where we're at.

We have our component accessing state from the store, through mapStateToProps. The state exists in the component now, but the component can't access it just yet.

First, we need to pass it to the connect function. The connect functions says, "Access to the store granted! Now... what state am I granting access to?"

So we pass in the function returning state, mapStateToProps, like this:

export default connect(mapStateToProps, {})(List) Radical!

We're almost there!

Now the component is capable of receiving that state as props, like it traditionally would from a parent component. Maybe we are mapping over it, and displaying each name on the screen in a div. Here's what this may look like!

const List = props => {
    return (
        <div>
            {
                props.names.map(name => {
                    return <div>{name}</div>
                })
            }
        </div>
    )
}

Awesome! But there is one final problem... Where does the action get called?

Typically there would be an input, so you could input a new name, and add it to the array - but, for simplicity sake, let's just add a button that adds the name Chris, when clicked! (Not very functional, but you see my point! :D)

We need to access that action creator function. Well, earlier we exported that function so we could import it where we need it, like in our List.js component!

import { addName } from "../actions"

The file location will depend on your directory structure, but it is common to have all actions exported from an index.js file in your actions directory, and then import from that directory. Don't worry too much about that now though!

Great, we have our function, but we can't just pass this function as props to our component just yet. This action is related to Redux, and with Redux we need to connect the action through the connect higher-order component, so when we return our action object, our reducer can accept it and perform accordingly!

Remember that extra space in the connect at the bottom of our List.js component? Let's fill that in with our addName function.

export default connect(mapStateToProps, {addName})(List);

Now, we can pass in our function as props (similar to our state), and use the function as we need!

const List = props => {
    return (
        <div>
            <button onClick={() => props.addName('Chris')}></button>
            {
                props.names.map(name => {
                    return <div>{name}</div>
                })
            }
        </div>
    )
}

I simply created a button, and added an onClick event listener, which triggers the addName function, and passing in 'Chris', like we set out to achieve!

Geez! that was a mission... but we made it! So, let's recap what is happening exactly.

The Redux Recap

We started with creating our store, and passed access to it through the provider, which wrapped our application. Then we created our initial state to use, and formed our reducer which manipulates the state. We built an action creator, addName which is a function that returns instructions for the reducer. These specific instructions said, "We want to add the name Chris to the names array!"

The reducer then takes that information and adds the name to the state. Our component accesses the state through connect, and receives the state through the mapStateToPropsfunction. We also import our action creator, addName, and pass it to connect as well.

The result? We can access our action creator, and our state, as props! However, we aren't passing this information through any other components, just pulling it directly from the store. Delivery straight to your door! Uber eats roc- I mean, Redux rocks!

I understand there is so much more to Redux, and many other things you can change to make everything easier and simpler to use, I just wanted to cover some of the basic foundations of it, and what has helped me understand it a bit better!

I would love to hear your thoughts/opinions on Redux. Thank you for reading !