Accessing Redux state in an action creator? Accessing Redux state in an action creator? javascript javascript

Accessing Redux state in an action creator?


There are differing opinions on whether accessing state in action creators is a good idea:

  • Redux creator Dan Abramov feels that it should be limited: "The few use cases where I think it’s acceptable is for checking cached data before you make a request, or for checking whether you are authenticated (in other words, doing a conditional dispatch). I think that passing data such as state.something.items in an action creator is definitely an anti-pattern and is discouraged because it obscured the change history: if there is a bug and items are incorrect, it is hard to trace where those incorrect values come from because they are already part of the action, rather than directly computed by a reducer in response to an action. So do this with care."
  • Current Redux maintainer Mark Erikson says it's fine and even encouraged to use getState in thunks - that's why it exists. He discusses the pros and cons of accessing state in action creators in his blog post Idiomatic Redux: Thoughts on Thunks, Sagas, Abstraction, and Reusability.

If you find that you need this, both approaches you suggested are fine. The first approach does not require any middleware:

import store from '../store';export const SOME_ACTION = 'SOME_ACTION';export function someAction() {  return {    type: SOME_ACTION,    items: store.getState().otherReducer.items,  }}

However you can see that it relies on store being a singleton exported from some module. We don’t recommend that because it makes it much harder to add server rendering to your app because in most cases on the server you’ll want to have a separate store per request. So while technically this approach works, we don’t recommend exporting a store from a module.

This is why we recommend the second approach:

export const SOME_ACTION = 'SOME_ACTION';export function someAction() {  return (dispatch, getState) => {    const {items} = getState().otherReducer;    dispatch(anotherAction(items));  }}

It would require you to use Redux Thunk middleware but it works fine both on the client and on the server. You can read more about Redux Thunk and why it’s necessary in this case here.

Ideally, your actions should not be “fat” and should contain as little information as possible, but you should feel free to do what works best for you in your own application. The Redux FAQ has information on splitting logic between action creators and reducers and times when it may be useful to use getState in an action creator.


When your scenario is simple you can use

import store from '../store';export const SOME_ACTION = 'SOME_ACTION';export function someAction() {  return {    type: SOME_ACTION,    items: store.getState().otherReducer.items,  }}

But sometimes your action creator need to trigger multi actions

for example async request so you need REQUEST_LOAD REQUEST_LOAD_SUCCESS REQUEST_LOAD_FAIL actions

export const [REQUEST_LOAD, REQUEST_LOAD_SUCCESS, REQUEST_LOAD_FAIL] = [`REQUEST_LOAD`    `REQUEST_LOAD_SUCCESS`    `REQUEST_LOAD_FAIL`]export function someAction() {    return (dispatch, getState) => {        const {            items        } = getState().otherReducer;        dispatch({            type: REQUEST_LOAD,            loading: true        });        $.ajax('url', {            success: (data) => {                dispatch({                    type: REQUEST_LOAD_SUCCESS,                    loading: false,                    data: data                });            },            error: (error) => {                dispatch({                    type: REQUEST_LOAD_FAIL,                    loading: false,                    error: error                });            }        })    }}

Note: you need redux-thunk to return function in action creator


I agree with @Bloomca. Passing the value needed from the store into the dispatch function as an argument seems simpler than exporting the store. I made an example here:

import React from "react";import {connect} from "react-redux";import * as actions from '../actions';class App extends React.Component {  handleClick(){    const data = this.props.someStateObject.data;    this.props.someDispatchFunction(data);  }  render(){    return (      <div>             <div onClick={ this.handleClick.bind(this)}>Click Me!</div>            </div>    );  }}const mapStateToProps = (state) => {  return { someStateObject: state.someStateObject };};const mapDispatchToProps = (dispatch) => {  return {    someDispatchFunction:(data) => { dispatch(actions.someDispatchFunction(data))},  };}export default connect(mapStateToProps, mapDispatchToProps)(App);