Published on

Redux

Authors
  • avatar
    Name
    Loc Truong
    Twitter

Introduction To Redux

A React application can share multiple points of data across components. In many cases, managing the data shared can become a complex task.

Redux is a library for managing and updating application states. It provides a centralized “store” for the state that is shared across your entire application, with rules ensuring that the state can only be updated in a predictable fashion using events called “actions”.

Redux works well with applications that have a large amount of global state that is accessed by many of the application’s components. The goal of Redux is to provide scaleable and predictable state management.

Store

In Redux, a store is a container that manages the global state of your application.

As the single source of truth, the store is the center of every Redux application. It has the ability to update the global state and subscribes elements of an application’s UI to changes in the state. Rather than accessing the state directly, Redux provides functions through the store to interact with the state.

Actions

In Redux, an action is a plain JavaScript object that represents an intention to change the store’s state. Action objects must have a type property with a user-defined string value that describes the action being taken.

Optional properties can be added to the action object. One common property added is conventionally called payload, which is used to supply data necessary to perform the desired action.

Reducers

In Redux, a reducer, also known as a reducing function, is a JavaScript function that takes the current state of the store and an action as parameters.

Reducers calculate the new state based on the action it receives. Reducers are the only way the store’s current state can be changed within a Redux application. They are an important part of Redux’s one-way data flow model.

Redux toolkit

npm install @reduxjs/redux-toolkit 
import React, { useReducer, SyntheticEvent  } from "react";
import { createSlice } from "@reduxjs/toolkit";

const authState = {
  isRequestingToken: "",
  username: "",
  token: "",
  error: ""
};

const authSlice = createSlice({
  name: "auth",
  reducers: {
    loginStart: (state, action) => {
      state.isRequestingToken = "yes";
      state.username = action.payload.username;
    },
    loginSuccess: (state, action) => {
      state.isRequestingToken = "no";
      state.token = action.payload.token;
    }
  },
  initialState: authState
});

const { loginStart, loginSuccess } = authSlice.actions;
const authReducer = authSlice.reducer;

export function SillyThings() {
  const [state, dispatch] = useReducer(authReducer, authState);

  function handleSubmit(event:SyntheticEvent) {
    event.preventDefault();
    const formData = new FormData(event.target as HTMLFormElement);
    const username = formData.get("username");

    dispatch(loginStart({ username }));

    fetch("https://api.valentinog.com/api/token-create/", {
      method: "POST",
      body: formData
    })
      .then(response => {
        if (!response.ok) throw Error(response.statusText);
        return response.json();
      })
      .then(json => dispatch(loginSuccess({ token: json.token })));
  }

  return state.token ? (
    <p>Welcome back {state.username}</p>
  ) : (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="username"> Username</label>
        <input type="text" id="username" name="username" />
      </div>
      <div>
        <label htmlFor="password">Password</label>
        <input type="password" id="password" name="password" />
      </div>
      <button type="submit">LOGIN</button>
    </form>
  );
}