RMT
RMT

Reputation: 1162

Organize Redux action type and state

What is the best practice to organize my action types and state when I have a large app? One issue might be that I want to use the same name because it is a similar action and a similar state.

Just for the discussion: what if I wanted to update two titles, do I need to use a name convention like FIRST_TITLE and SECOND_TITLE for the action type and firstTitle and seccondTitle for the state?

I am open to better solutions too.

Upvotes: 1

Views: 1011

Answers (2)

Brian
Brian

Reputation: 1036

You can use something like redux-auto. It generate actions and reducers from your file system.

We are using it in product for a large project and its has really helped bring down the complexity. It's nice that each transformation has its own file and this becomes your generated action name + async code co-located to the same file.

A summary:

It takes the ideas of reducer composition one step further. Where instead of having a file that represents your reducer and creating individual actions functions.

redux-auto's approaches to have folders with individual JS files representing each action/transformation on the state and dynamically exposing this as functions

example

└── store/
    ├──user/
    │  └── index.js
    │  └── changeName.js
    └──posts/
       └── index.js
       └── delete.js

Now from anyway in your app you can write

import actions from 'redux-auto'
...
actions.user.changeName({name:"bob"})

store/user/changeName.js

export default function (user, payload) {
    return Object.assign({},user,{ name : payload.name });
}

Thats is!

If you want to listen for redux actions in third-party reducers. You can use as loose quality check against the function.

action.type == actions.user.changeName // "USER/CHANGENAME"

For something more advanced you can even see if an action is owned by a specific reducer

// Returns true if it's an action specifically for user
if(action.type in actions.user) 

You can read more on the project page

Upvotes: 0

OlliM
OlliM

Reputation: 7113

In a large app, I've organized my code into modules, each with their own reducer, actions etc. Each module exports the action types and action creators, I use those exlusively and never just pass a string as type. This prevents any naming conflicts between modules - in fact I try to keep the action names short.

modules/items/actionTypes.js:

export const name = "items";

export const UPDATE_TITLE = `${name}/UPDATE_TITLE`;

modules/items/actions.js

import * as actionTypes from "./actionTypes";

export const updateTitle = (title) => ({
  type: actionTypes.UPDATE_TITLE,
  payLoad: title,
});

modules/items/reducer.js

import * as actionTypes from "./actionTypes";

const initialState = { title: "" };

const reducer = (state = initialState, action) {
  switch(action.type) {
    case actionTypes.UPDATE_TITLE: {
      return {
        ...state,
        title: action.payload,
      };
    }
  }
}

export default reducer;

modules/comments/actionTypes.js

export const name = "comments";

export const UPDATE_TITLE = `${name}/UPDATE_TITLE`;

modules/comments/actions.js

import * as actionTypes from "./actionTypes";

export const updateTitle = (title) => ({
  type: actionTypes.UPDATE_TITLE,
  payLoad: title,
});

modules/comments/reducer.js

import * as actionTypes from "./actionTypes";
import * as itemActionTypes from "../items/actionTypes";

const initialState = { title: "" };

const reducer = (state = initialState, action) {
  switch(action.type) {
    case actionTypes.UPDATE_TITLE: {
      return {
        ...state,
        title: action.payload,
      };
    }
    case itemActionTypes.UPDATE_TITLE: {
      // Do something with the updated item title
    }
  }
}

export default reducer;

rootReducer.js

import { combineReducers } from "redux";
import { default as itemsReducer } from "modules/items/reducer";
import { default as commentsReducer } from "modules/comments/reducer";

export default combineReducers({
  items: itemsReducer,
  comments: commentsReducer,
});

EDIT: added reducers to answer comment

Upvotes: 0

Related Questions