Small update on Redux usage
Tags: redux, react, architecture, codestyle
Published: 2019-12-14 10:54:24

So the first Redux version was developed somewhere around 5 years from now and a lot has changed since then.

![redux-first-releast](https://thepracticaldev.s3.amazonaws.com/i/h0d7zsc9w3su6bnied62.png)

Not only React improved the way our code works for the end-users but also we, as developers, changed the way we use React. Best practices come and go, leaving us with the code that other, new developers, might not understand the purpose of. Remember that `PureComponent` thing? That it was added in the time where everyone was obsessed with React performance before even having any issues with that? Or smart and dumb components?

{% twitter 579966838525792257 %}

Why those practices change is another topic, I guess more related to the way software products are developed rather than tied to React or Front End. So here I just wanted to share a few best practices I believe made Redux usage better over the years.

## Folder structure

So far I've mostly seen a separation of files based on their purpose:

![redux folders separated to actions/reducers/selectors](https://thepracticaldev.s3.amazonaws.com/i/f0b5ai5xdef2gv5hlmi0.png)

Then Redux Ducks came into play, making people to separate files and folders by their features or model they work with. This is a great approach suggested by the [Redux Style Guide](https://redux.js.org/style-guide/style-guide#structure-files-as-feature-folders-or-ducks)

![Redux Feature Folders structure](https://thepracticaldev.s3.amazonaws.com/i/sk42epj0afz6ll7n1pgk.png)

Notice that files were separated only when the feature became too big to manage in one file. First, `actions.ts` were separated from `index.ts` file. Then came others, making the index to export `createReducer` only, with imported `reducer` and initial state. This enables to dispatch specific actions from the specific feature. Why this approach works well? I will agree with [Monica Lent](https://www.youtube.com/watch?v=TqfbAXCCVwE) that constraints make software easier to maintain. In this case, we constrain code to their features.

> But it never works like that in real life! Domain models are interconnected! Actions to one module can cause changes in another! That's real life!

Alright, that's correct. So how about...

## Event-driven reducers

Event-driven reducers mean that instead of making action type names to describe what you want to change in the store, you describe what just happened. E.g. instead of `ADD_ITEM` you say `ITEM_ADDED` and bum your reducer now reacts to the event, that item was added to the basket. Then it means that if you want some other reducer to change the state based on this action, you just add to that another reducer one more switch clause. If you want to know more, check out [this talk by Yazan Alaboudi](https://www.youtube.com/watch?v=K6OlKeQRCzo&feature=youtu.be&t=2627).

And small example from [Redux Style Guide](https://redux.js.org/style-guide/style-guide#model-actions-as-events-not-setters)

Compare this two:

```js
{ type: "food/orderAdded",  payload: {pizza: 1, coke: 1} }
```

with

```js
{
    type: "orders/setPizzasOrdered",
    payload: {
        amount: getState().orders.pizza + 1,
    }
}

{
    type: "orders/setCokesOrdered",
    payload: {
        amount: getState().orders.coke + 1,
    }
}
```

With more complicated examples it gets even more beneficial, not only on the code sources side, but on the cognitive load as well, perceiving your reducers not as "for this action -> update this field", but rather "when this happens -> this updates".

## It's all interconnected 🔝

So you probably don't need `const ADD_ITEM_TO_THE_BASKET = 'ADD_ITEM_TO_THE_BASKET';`. If your store is strictly separated by domain models or features and not by your UI code, you can separate events that occur in your system by such features. So your events can look like

```js
{ type: 'food/orderAdded', payload: { /* order info */ }
{ type: 'posts/clapped', payload: { times: 11 } }
```

This way your actions are safe. Logic changes, how we handle events can change as well, but events doesn't. Or at least not that often. You can read about it [there](https://redux.js.org/style-guide/style-guide#write-meaningful-action-names).

Second, you can easily react to the event from multiple places in your store. So instead of having:

```js
dispatch({ type: 'ADD_CLAP' });
dispatch({ type: 'SET_COMMENTS_AVAILABLE', payload: true });
```

you can have multiple reducers reacting to the same event:

```js
dispatch({ type: 'posts/clapped', payload: { /* item */ });

// in your reducers

// posts.js
  case 'posts/clapped':
    return { ...state, claps: state.claps + 1 };

// comments.js
  case 'posts/clapped':
    return { ...state, commentsAvailable: true }; 

```

And so we're moving our logic to reducers, instead of making calculations in components' code, `redux-thunk`s, or `redux-sagas`. We know the logic belongs to the reducer, so we move it there. You can read more about it [there](https://redux.js.org/style-guide/style-guide#put-as-much-logic-as-possible-in-reducers).

So as you can see, best practices, which enable us to write maintainable Redux store are all interconnected: with one thing you can easier do another, without sacrificing on anything. This post wasn't intended to be "look what I found", or "one more best practice in Redux". These are just simple and short rules you can incorporate (you probably did already, partially, unconsciously, because it's a natural approach) to your Redux store architecture. And there are more of these already described in [Redux Style Guide](https://redux.js.org/style-guide/style-guide), concluded by developers to make your life easier. Please, take a quick look, maybe you can find something you have question about to ask here!

Be good, smile and tell jokes to each other!

###### Cover image reference: [React Redux Tutorial for Beginners: Simply Explained](https://chriscourses.com/blog/redux)