Introduction to State Management with Redux
Tags: react, redux, webdev, javascript
Published: 2021-01-25 01:47:25

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


With Redux, we can use it to store data in a central location in our JavaScript app. It can work alone and it’s also a popular state management solution for React apps when combined with React-Redux.

In this article, we’ll look at how to create a basic store in the app and use it.

### Installation

Redux is available as an NPM package. We can install it by running:

```
npm install --save redux
```

with NPM or:

```
yarn add redux
```

with Yarn.

### Basic Example

We can use redux to store the state of an app by creating a store and reducer.

Then we can subscribe to the store to get the data and dispatch actions to make changes to the state.

For example, we can write:

```
import { createStore } from "redux";

function counter(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + action.payload || 1;
    case "DECREMENT":
      return state - action.payload || 1;
    default:
      return state;
  }
}

let store = createStore(counter);
store.subscribe(() => console.log(store.getState()));

store.dispatch({ type: "INCREMENT", payload: 2 });
store.dispatch({ type: "DECREMENT", payload: 1 });
```

In the code above, we have the `counter` reducer function which gets the action type and payload and then applies it accordingly.

The `counter` function checks for action type `INCREMENT` and `DECREMENT` and return the new state with the `payload` added to it.

Then we create the `store` by running:

```
let store = createStore(counter);
```

After that, we can subscribe to the store by calling `subscribe` on the store and then call `getState` within the callback for it as follows:

```
store.subscribe(() => console.log(store.getState()));
```

Then we can dispatch actions to the store by calling `dispatch` on it with an object with the `type` and `payload` , which will be passed into the `counter` function in the `action` parameter.

Therefore, the `state` will be updated by the `action` since for the first `dispatch` call:

```
store.dispatch({ type: "INCREMENT", payload: 2 });
```

The `type` will be passed in as `action.type` and payload will be set as `action.payload` to `counter` .

`action.type` is `‘INCREMENT’` and `action.payload` is 2.

Likewise, `action.type` is `‘DECREMENT’` and `action.payload` is 1 in the second call.

Note that we don’t mutate the state directly in `counter` . We return a new state by deriving it from the existing state.

### Three Principles of Redux

Three principles apply to the way Redux is built.

#### Single Source of Truth

Redux stores state in a single place. This makes getting data easy since we only have to get it in one place.

Debugging is also easy because of that. This makes development faster.

Some functionality that was hard to implement now can be easy since now the state is stored in a single tree.

#### State is Read-Only

The state is read-only so it can’t be changed by accident. We have to express an intent to change the state.

There aren’t subtle race conditions to watch out for since all changes are centralized and happen one by one in strict order.

Since actions are just plain objects, they can be logged, serialized, stored and replayed for debugging and testing purposes.

#### Changes are Made With Pure Functions

Reducers are pure functions that take the previous state and action and return the next state. We return new state objects instead of mutation previous state.

We can start with a single reducer and then split it off into smaller reducers that management other parts of the state tree.

We can control how they’re called, pass additional data, or make reusable reducers.

### Flux Architecture

Redux concentrates all model update logic in one layer of an app. This is one part of the Flux architecture that’s adopted by Redux.

Redux doesn’t have a dispatcher. It relies on pure functions instead of event emitters to change state.

Pure functions are easy to compose and doesn’t need extra management.

Redux assumes that we never mutate our data. We should always return new objects. This is easy now that we have the spread operator for objects.

![](https://cdn-images-1.medium.com/max/800/0*qfT1SkSA4AZa2x-r)Photo by [Kelly Sikkema](https://unsplash.com/@kellysikkema?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

### RxJS

We can turn a Redux store into an Rxjs Observable by subscribing to it and calling `nexr` to return the latest state.

For example, we can write:

```
import { createStore } from "redux";

function counter(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + action.payload || 1;
    case "DECREMENT":
      return state - action.payload || 1;
    default:
      return state;
  }
}

let store = createStore(counter);

function toObservable(store) {
  return {
    subscribe({ next }) {
      const unsubscribe = store.subscribe(() => next(store.getState()));
      next(store.getState());
      return { unsubscribe };
    }
  };
}

const counterObservable = toObservable(store);

counterObservable.subscribe({
  next(count) {
    console.log(count);
  }
});

store.dispatch({ type: "INCREMENT", payload: 2 });
store.dispatch({ type: "DECREMENT", payload: 1 });
```

In the code above, we have:

```
function toObservable(store) {
  return {
    subscribe({ next }) {
      const unsubscribe = store.subscribe(() => next(store.getState()));
      next(store.getState());
      return { unsubscribe };
    }
  };
}

const counterObservable = toObservable(store);

counterObservable.subscribe({
  next(count) {
    console.log(count);
  }
});

store.dispatch({ type: "INCREMENT", payload: 2 });
store.dispatch({ type: "DECREMENT", payload: 1 });
```

The `toObservable` returns an Observable which we can subscribe to since it returns a `subscribe` method.

The Redux store’s `subscribe` method returns an `unsubscribe` function so we can unsubscribe to it when we no longer need it.

Then when we call `dispatch` above, we’ll get the new values logged in the `next` function above.

### Conclusion

We can store an app’s data in a central place with Redux. To do this, we create a store and then subscribe to it to get the latest state from it.

Then we call `dispatch` on the store with a plain object with the action type and payload to change the store to the latest state.