DEV Community

asiddharth94
asiddharth94

Posted on

Introduction to Redux pattern

As the documentation reads - Redux is a predictable state container for JS apps .

Let's break this up -

  • predictable - Redux helps you write applications that behave consistently (we update the state using 'reducers', which are pure functions. We'll get to reducers later), run in different environments (client, server, and native). All state transitions are explicit and it is possible to keep track of them.

  • state container - Redux 'store' is an object which holds the whole global state of our app. And then, we can just get the values from the store to wherever we need in our app. Awesome! Right?

  • for JS apps - Redux can be used with vanilla JS or any JS framework. (People, No! It is not a React thing 😛)

Redux can be described in Three fundamental Principals -

  1. Single source of truth - A fancy way of saying that we have one single big object that describes the entire state of the app. (Note - It is also a common pattern to keep only important state in Redux store while keeping UI specific state like form-inputs in component’s state)

  2. State is read-only - The state is immutable. The only way to change the state is to emit an 'action'. (Don't worry, if you don't know what 'actions' are yet. Keep reading! You'll know! 🙂)

  3. Changes using pure functions - We write pure reducers which takes in 'currentState' and an 'action', and returns the 'nextState'. (pure - given same input, the output is always same)

Cool! Let's get Coding!
Image description

An Action is a plain object which has two properties -
'type' (name of action: string)
'payload' (the value to be updated)

{
   type: 'add_todo',
   payload: 'learn redux'
}
Enter fullscreen mode Exit fullscreen mode

A Reducer is a pure function that gets two arguments
(current/prev state & action) and returns the new state based on the action's type.

const reducer = (state={todo: [], otherValues: {}}, action) => {
  switch (action.type) {
    case "add_todo":
      return {
         ...state,
         todo: [...state.todo, action.payload]
      };
    default:
      return state;
  }
}
Enter fullscreen mode Exit fullscreen mode

Next, store!

As we know, store is a single object which holds the complete global state of our app. Redux provides us with 'createStore' api to which we pass our reducer and that is it, we have our global state, i.e, the store.

import { createStore } from "redux";

let store = createStore(reducer);
Enter fullscreen mode Exit fullscreen mode

Next, we need to subscribe to the store to listen when the store is updated and thus, update our UI accordingly.

store.subscribe(() => console.log(store.getState()));
Enter fullscreen mode Exit fullscreen mode

Note - subscribe() is not the only way as different frameworks have different view binding libraries for this use case, e.g, react-redux.

Last thing! Now we know that our store can only be updated by dispatching actions! Let's do that! 🚀

store.dispatch({ type: "add_todo", payload: "learn redux" });

Enter fullscreen mode Exit fullscreen mode

ANNNDDDDD, THAT IS IT ! YAY !

Here is a working link! 🙂

MORE -
As our app grows, we might need to have multiple reducers to manage different parts of our application's state.

The combineReducers() takes an object which has these multiple reducers and returns a single reducer which is a combination of all reducers passed to it. We can then pass this to createStore().

const rootReducer = combineReducers({
      one: reducerOne,
      two: reducerTwo
});

const store = createStore(rootReducer);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)