Skip to content

Redux - Store

The Store is the heart of a Redux application. It’s a single JavaScript object that holds the complete state tree of your application. Think of it as the single source of truth for all your application data.

Key characteristics of the Redux store:

  • Holds the application state.
  • Allows access to the state via getState().
  • Allows state to be updated via dispatch(action).
  • Registers listeners via subscribe(listener).
  • Unregisters listeners via the function returned by subscribe(listener).

Crucially, there should only be one store in a Redux application. Managing multiple stores would defeat the purpose of having a single, predictable state container.

Section titled “Creating a Store with Redux Toolkit (Recommended)”

The modern and recommended way to create a Redux store is using the configureStore function from @reduxjs/toolkit. It simplifies the setup process significantly.

import { configureStore } from '@reduxjs/toolkit';
// Import your reducers (likely created with createSlice or combineReducers)
import rootReducer from './reducers';
const store = configureStore({
reducer: rootReducer, // Pass the root reducer (or an object of slice reducers)
// Middleware and DevTools are automatically configured!
});
export default store;

configureStore handles several things automatically:

  • Combines your slice reducers (if you provide an object) into the root reducer.
  • Applies helpful middleware by default, including redux-thunk for async logic.
  • Sets up the Redux DevTools Extension integration automatically (in development mode).

You can optionally provide preloadedState (initial state) and customize middleware or enhancers if needed.

While configureStore is recommended, understanding the original createStore API helps grasp the fundamentals. (Note: createStore is now marked as @deprecated in favor of configureStore).

import { createStore, applyMiddleware } from 'redux';
import { thunk } from 'redux-thunk'; // Example middleware
import rootReducer from './reducers';
const initialState = {}; // Optional initial state
// Basic store
// const store = createStore(rootReducer, initialState);
// Store with middleware
const store = createStore(
rootReducer,
initialState,
applyMiddleware(thunk) // Apply middleware explicitly
);
export default store;

The createStore function takes the root reducer as the first argument. Optional arguments include the preloadedState (initial state) and an enhancer (typically the result of applyMiddleware).

Once the store is created (using either method), you interact with it using these core methods:

Returns the current state tree of your application. It’s the only way to access the state directly.

const currentState = store.getState();
console.log(currentState);

This is the only way to trigger a state change. You pass an action object (or a function, if using Thunk middleware) to dispatch. Redux then calls your reducer with the current state and the action, updating the state based on the reducer’s logic.

// Dispatching a plain action object
store.dispatch({ type: 'counter/increment' });
// Dispatching a thunk action (if thunk middleware is configured)
// store.dispatch(fetchUserData());

Registers a callback function (listener) that will be called every time an action is dispatched and the state might have changed. It’s commonly used to update the UI in response to state changes (though UI libraries like React Redux handle this automatically).

The subscribe method returns a function that you can call to unsubscribe the listener.

const handleChange = () => {
console.log('State changed:', store.getState());
};
const unsubscribe = store.subscribe(handleChange);
// Later, to stop listening:
unsubscribe();

In typical applications using UI frameworks like React or Angular, you won’t call subscribe directly very often. Libraries like react-redux use the store’s subscription mechanism internally to connect your components to the Redux state and re-render them automatically when needed.