React Action Creator and Action Type Naming Convention?

Viewed 1939

Are there any official naming convention on naming action creators and action.types

Looking over tutorials the theme of the action creator and action type is to name the action type pretty much one to one with action creator.

To use an example lets say we have an application fetching blog posts

The tutorial (top rated Udemy tutorial) used the following naming convention with asynchronous action creator:

export const fetchPosts = () => async dispatch => {
    const response = await postsAPI.get('/posts');

    dispatch({type: 'FETCH_POSTS', payload: response.data});
};

However, wouldnt it make more sense to name the action objects more precisely (to signify success or failure) to what is being dispatched. Rather than matching action creator function name with action type, along the lines of:

export const fetchPosts = () => async dispatch => {
    const response = await postsAPI.get('/posts');
    
    if (response.status === 200) {
       dispatch({type: 'FETCHED_POSTS', payload: response.data});
    } else {
        dispatch({type: 'FAILED_TO_FETCH_POSTS', payload: response});
    }
};
2 Answers

Yes, the official style guides suggests to write action types as domain/eventname.

This goes along with a few other things from the style guide.

Adding to that, I prefer my actions to be in the past like todos/added when they describe something that happened in the application or something the user did, and to be in the imperative like todos/save when they describe a side effect that should be handled in a middleware (which will then maybe do an API request and end up in a todos/saved action to actually lead to changes in a reducer).

A few more things are implicitly done by RTK, for example createAsyncThunk will autmatically create three actions for every thunk: yourActionPrefix/pending, yourActionPrefix/fulfilled and yourActionPrefix/rejected.

I agree with you in that communicating the specific type of object being dispatched improves clarity, but I also think it's important to show how actions are related to each other. This can be achieved by using some prefix for related actions, along with suffixes to denote different cases.

e.g. So with the prefix FETCH_POSTS, you can have action names like

  • FETCH_POSTS_REQUEST
  • FETCH_POSTS_SUCCESS
  • FETCH_POSTS_FAILURE
export const fetchPosts = () => async dispatch => {
    const response = await postsAPI.get('/posts');
    
    if (response.status === 200) {
       dispatch({type: 'FETCH_POSTS_SUCCESS', payload: response.data});
    } else {
        dispatch({type: 'FETCH_POSTS_FAILURE', payload: response});
    }
};

One further step you could take is to use a constants object that defines these actions names. This is because action names are reused in several places (action creators, reducers, unit tests, etc), and having action names defined as constants enforces consistency and readability.

export const POSTS_API_ACTIONS = {
   FETCH_POSTS_REQUEST: 'FETCH_POSTS_REQUEST',
   FETCH_POSTS_SUCCESS: 'FETCH_POSTS_SUCCESS',
   FETCH_POSTS_FAILURE: 'FETCH_POSTS_FAILURE',
   DELETE_POSTS_REQUEST: 'DELETE_POSTS_REQUEST',
   ...
}

export const fetchPosts = () => async dispatch => {
    const response = await postsAPI.get('/posts');

    if (response.status === 200) {
       dispatch({type: POSTS_API_ACTIONS.FETCH_POSTS_SUCCESS, payload: response.data});
    } else {
        dispatch({type: POSTS_API_ACTIONS.FETCH_POSTS_FAILURE, payload: response});
    }
};
Related