DEV Community

Renato Rocha
Renato Rocha

Posted on

Flux, Redux and React Redux overview

Flux

Flux pattern was proposed by Facebook for building client-side web applications. This pattern, according to Facebook, is divided in parts: dispatcher, stores, and the views.

The Flux documentation warns that this pattern do not be confused with MVC once controllers do exist in a Flux application, but they are controller-views.

Flux vs MVC

Flux pattern has a unidirectional data flow. When a user interacts with a React view, the view propagates an action through a central dispatcher, to the various stores that hold the application's data and business logic, which updates all of the views that are affected.

Dispatcher

In application all data flow through the dispatcher that manages it. It is a simple mechanism for distributing the actions to the stores. Each store registers itself and provides a callback. When an action is dispatcher, all registered stores receive the action.

Stores

Stores contain the application state and logic. Registers itself with the dispatcher and provides it with a callback. This callback receives the action as a parameter. Within the store's registered callback, a switch statement based on the action's type is used to interpret the action and to provide the proper hooks into the store's internal methods.

This allows an action to result in an update to the state of the store, via the dispatcher

Controller-Views

Normally in the top of the view hierarchy, controller-views, listen for events that are broadcast by the stores. After receive the broadcast it requests the new data to the stores. Then calls its own setState() causing its render() and your descendants.

Actions

An action is a function wich the dispacher will trigger it to the stores. This function may receive params and return an object with a type an perhaps a payload.

function doSomeThing() {
  return {
    type: "DO_SOME_THING",
    payload: { data }
  };
}

Redux

Redux is a state container for JavaScript apps that implements some parts of the Flux pattern and is founded on three principles.

Core Principles

  • Single source of truth: there is a single object that maintains the entire state of the application.

  • State is read-only: the state can not be changed directly, to this an action need be be emitted expressing intention.

  • Changes are made with pure functions: when an action is emitted it is received by reducers that are pure functions. The reducer will take as parameters the previous state, an action and will returns the next state.

JavaScript example

As Redux is a state container for JavaScript application, we can try it without another libray such as React.

Install

  mkdir redux_test && cd redux_test && yarn init -y
  yarn add redux

and from the redux documentation we following a simple exemplo:

const redux = require("redux");
const readline = require("readline");
const { promisify } = require("util");

const reader = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

reader.question[promisify.custom] = question => {
  return new Promise(resolve => {
    reader.question(question, resolve);
  });
};

const INITIAL_STATE = 0;
/**
 * -- reducer --
 * @param {number} state
 * @param {{type: string, payload: number}} action
 */
function counter(state = INITIAL_STATE, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + action.payload;
    default:
      return state;
  }
}

// Create a Redux store holding the state of your app.
const store = redux.createStore(counter);

// You can use subscribe() to update the UI in response to state changes.
store.subscribe(() => console.log(`store.subscribe: ${store.getState()}`));

const question = promisify(reader.question);

/**
 * Dispatch an action to store: store.dispatch
 */
async function read() {
  while (true) {
    await question("Next inc number\n")
      .then(inc => store.dispatch({ type: "INCREMENT", payload: Number(inc) }))
      .catch(err => console.log(err));
  }
}

read();

and we can run with:

node script_name.js

typing some positive and negative number to see the results.

React-Redux

As Redux is a state container for JavaScript applications, this can be used with any UI framework that has a binding library for the Redux.

The React Redux is the official Redux binding for React applications. This is maintained directly by the Redux team keeping updated with any changes in the Redux.

Example

With the store and reducer created at Redux we need pass the store through the component tree and we can use hooks to access it.

import React from "react";
import ReactDOM from "react-dom";
import Counter from "./Counter";

import { Provider } from "react-redux";
import store from "./redux/store";

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

In the counter component:

import React from "react";
import { useSelector, useDispatch } from "react-redux";

export const Counter = () => {
  const dispatch = useDispatch();
  const counter = useSelector(state => state.counter);

  return (
    <>
      <span>`counter: ${counter}`</span>
      <button onClick={() => dispatch({ type: "INCREMENT", payload: 1 })}>
        Increment
      </button>
    </>
  );
};

In this article, an overview of Flux, Redux and React Redux was taken: the first (Flux) is a pattern proposed by Facebook that separates business logic from visualization; second (Redux), which is a library that implements some parts of Flux and, finally, React Redux, a library used as a link between React applications and Redux library.

Top comments (0)