Back to Basics: What's the Difference between an Action and an Action Creator in Redux.js?

Redux

Looking at Redux.js for the first time can be overwhelming because there are so many moving parts. There are a few similar-sounding terms to learn such as actions, action types, and action creators. Understanding what they are and how to use them is the first step to adding Redux to your application.

Action Type

An action type is a string that simply describes the type of an action. They're commonly stored as constants or collected in enumerations to help reduce typos and because programmers love organization. I've found it helpful to structure my action types like this:

export const Actions = {  GET_USER_DETAILS_REQUEST: 'GET_USER_DETAILS_REQUEST',  GET_USER_DETAILS_SUCCESS: 'GET_USER_DETAILS_SUCCESS',  GET_USER_DETAILS_FAILURE: 'GET_USER_DETAILS_FAILURE',  UPDATE_USER_DETAILS_REQUEST: 'UPDATE_USER_DETAILS_REQUEST',  UPDATE_USER_DETAILS_SUCCESS: 'UPDATE_USER_DETAILS_SUCCESS',  UPDATE_USER_DETAILS_FAILURE: 'UPDATE_USER_DETAILS_FAILURE',  // more...};

Action

An action is like a message that we send (i.e. dispatch) to our central Redux store. It can literally be anything. But ideally we want to stick to an agreed-upon pattern. And the standard pattern is as follows (this is a TypeScript type declaration):

type Action = {    type: string;    // Actions MUST have a type    payload?: any;   // Actions MAY have a payload    meta?: any;      // Actions MAY have meta information    error?: boolean; // Actions MAY have an error field                     // when true, payload SHOULD contain an Error};

(The question marks mean the property is optional. So you only need the type property at a minimum).

An action to fetch the user named Dan might look something like this

{    type: 'GET_USER_DETAILS_REQUEST',    payload: 'Dan'}

But you don't typically hardcode an action like this. You'd use an action creator.

Action Creator

As you might expect, an action creator is a function that creates and returns an action. Okay well... this is not always true. But for the purposes of learning Redux, you can pretend it's true for now.

Simple action creators look like this:

// in ES5 (also valid in ES6)export function getUserDetailsRequest(id) {  return {    type: Actions.GET_USER_DETAILS_REQUEST,    payload: id,  };}// in ES6export const getUserDetailsRequest = id => ({  type: Actions.GET_USER_DETAILS_REQUEST,  payload: id,});

(Note: If you're concerned about too much 'boilerplate' then redux-actions will help you greatly reduce it).

When writing basic Redux, an action creator simply returns an action. You would typically dispatch the action to your store immediately.

store.dispatch(getUserDetailsRequest('Dan'));

Although, realistically, you'll be doing this via dispatch properties that are passed into a React component like this:

// ES5export function mapDispatchToProps(dispatch) {    return {        onClick: function() { dispatch(getUserDetailsRequest('Dan')); }    };}// ES6export const mapDispatchToProps = dispatch => ({  onClick: () => dispatch(getUserDetailsRequest('Dan'))});

Later on, you'll have to deal with asynchronous actions such as making an AJAX call to the server. If you choose to use redux-thunk to manage your asynchronous code then you'll have complex action creators that dispatch multiple actions directly to the store rather than returning a single action for you to dispatch.

Personally, I prefer redux-saga over redux-thunk. With redux-saga, your action creators stay simple.

Further Reading

Level up Your React + Redux + TypeScript

for free with articles, tutorials, sample code, and Q&A.