DEV Community

loading...
Cover image for Redux Basics Cheat Sheet πŸ“–

Redux Basics Cheat Sheet πŸ“–

danielkrupnyy profile image Daniel Krupnyy ・Updated on ・3 min read

Basics

scheme
scheme

All components states are stored in the global state. Components can read information from it, but cannot directly change something in it.
To change the global state, components create Actions objects and submit them to the Redux Store. Such operations are called dispatches.
The Redux Store in turn uses the Reducer function to update the state.


Reducer

This is a function that is used to store logic. Accepts state and action (simple object).

const reducer = (state = 0, action) => {
  switch (action.type) {
    case "INC":
      return state + 1;
    default:
      return state;
  }
};

let state = reducer(undefined, {});

state = reducer(state, { type: "INC" });
Enter fullscreen mode Exit fullscreen mode

If state is undefined, then you need to return the original initialState.
If the action type is unknown, then you need to return state unchanged.

Reducer must be a pure function! This means that:

  1. The return value depends only on the arguments (you can only work with arguments)
  2. The function has no side effects (changing external data or changing arguments)

Redux Store

The redux store's job is to coordinate data in a react app.

import { createStore } from "redux";

const reducer = (state = 0, action) => {
  switch (action.type) {
    case "INC":
      return state + 1;
    default:
      return state;
  }
};

// Creating store (by default β€” 0)
const store = createStore(reducer);

// Subscriptions on changes in store 
store.subscribe(() => [console.log(`store changed: ${store.getState()}`)]);

// Handling new actions
store.dispatch({ type: "INC" });
store.dispatch({ type: "INC" });
Enter fullscreen mode Exit fullscreen mode

Counter example:

import { createStore } from "redux";

const reducer = (state = 0, action) => {
  switch (action.type) {
    case "INC":
      return state + 1;
    case "DEC":
      return state - 1;
    default:
      return state;
  }
};

const store = createStore(reducer);

const dec = document.getElementById("dec");
const inc = document.getElementById("inc");

dec.addEventListener("click", () => store.dispatch({ type: "DEC" }));
inc.addEventListener("click", () => store.dispatch({ type: "INC" }));

const update = () => {
  const counter = document.getElementById("counter");
  counter.textContent = store.getState();
};

store.subscribe(update);
Enter fullscreen mode Exit fullscreen mode

Together with the type of action in reduce through action, you can also transfer additional information to perform this very action:

import { createStore } from "redux";

const reducer = (state = 0, action) => {
  const { type, payload } = action;

  switch (type) {
    case "INC":
      return state + 1;
    case "DEC":
      return state - 1;
    case "RND":
      return state + payload;
    default:
      return state;
  }
};

const store = createStore(reducer);

const dec = document.getElementById("dec");
const inc = document.getElementById("inc");
const rnd = document.getElementById("rnd");

dec.addEventListener("click", () => store.dispatch({ type: "DEC" }));
inc.addEventListener("click", () => store.dispatch({ type: "INC" }));

// ---
rnd.addEventListener("click", () => {
  const payload = Math.floor(Math.random() * 10 + 1);
  store.dispatch({ type: "RND", payload });
});
// ---

const update = () => {
  const counter = document.getElementById("counter");
  counter.textContent = store.getState();
};

store.subscribe(update);
Enter fullscreen mode Exit fullscreen mode

Simplifying your code: Action Creator & bindActionCreators

Action Creator

Action Creator is a separate function that creates action objects, making it easy to write code:

const inc = () => ({ type: "INC" });
const dec = () => ({ type: "DEC" });
const rnd = (payload) => ({ type: "RND", payload });
Enter fullscreen mode Exit fullscreen mode

bindActionCreators

bindActionCreator is binds any accepted actionCreator to dispatch:

const store = createStore(reducer);
const { dispatch } = store;

const incDispatch = () => dispatch(inc());
const decDispatch = () => dispatch(dec());
const rndDispatch = (payload) => dispatch(rnd(payload));

// bindActionCreator working like that
const bindActionCreator = (creator, dispatch) => (...args) => {
  dispatch(creator(...args));
};

// Code is shorter now
const incDispatch = bindActionCreator(inc, dispatch);
const decDispatch = bindActionCreator(dec, dispatch);
const rndDispatch = bindActionCreator(rnd, dispatch);
Enter fullscreen mode Exit fullscreen mode

Redux has its own bindActionCreators function:

import { createStore, bindActionCreators } from "redux";

const incDispatch = bindActionCreator(inc, dispatch);
const decDispatch = bindActionCreator(dec, dispatch);
const rndDispatch = bindActionCreator(rnd, dispatch);
Enter fullscreen mode Exit fullscreen mode

The difference from a self-written function is that bindActionCreators can take an object of a set of actions as the first argument:

const { incDispatch, decDispatch, rndDispatch } = bindActionCreators(
  {
    incDispatch: inc,
    decDispatch: dec,
    rndDispatch: rnd,
  },
  dispatch
);
Enter fullscreen mode Exit fullscreen mode

The keys of such an object will be the names of the functions that we want to receive. In the case of a set of actions, bindActionCreators returns an object with ready-made functions that can be destructed:

import { createStore, bindActionCreators } from "redux";
import reducer from "./reducer";
import * as actions from "./actions"; // Import all actions in object format

const update = () => {
  const counter = document.getElementById("counter");
  counter.textContent = store.getState();
};

const store = createStore(reducer);
const { dispatch } = store;

const { inc, dec, rnd } = bindActionCreators(actions, dispatch);

store.subscribe(update);

document.getElementById("inc").addEventListener("click", inc);
document.getElementById("dec").addEventListener("click", dec);
document.getElementById("rnd").addEventListener("click", () => {
  const payload = Math.floor(Math.random() * 10);
  rnd(payload);
});
Enter fullscreen mode Exit fullscreen mode

Thanks for reading! ❀️
You can also check out my JavaScript Basic Type Conversions Cheat Sheet
If you have something to add, please, describe in the comments πŸ‘‡πŸ»

Discussion (2)

pic
Editor guide
Collapse
andrewbaisden profile image
Andrew Baisden

Great info here thanks for sharing it.

Collapse
danielkrupnyy profile image
Daniel Krupnyy Author

Your'e welcome!