V. Application state store - 24CaretSolutions/2b_n4tive GitHub Wiki

Store structure

There are three main levels in the central application store.
On the first level the store has the following properties:

data - keep any data collected from api server
screen - keep any state related to application’s screens and its visual representations (or UI state)

Inside data section values are grouped by api routes:

data: {
  commnets: {},
  events: {},
  games: {},
  notifications: {},
  users: {}
}

Inside screen section values are grouped by UI elements:

screen: {
  alert: {},
  searchBar: {}
}

The third level contains items and their values.

Action types

We define action types as a string constant, put them in actionTypes.js file and import where it is necessary. We add prefix to make them more specific. For prefix use name of the store item which the action related to. We use verbs to name action types.

export const UPDATE_CURRENT_USER = 'users/UPDATE_CURRENT_USER';

Actions

Typical structure of an action object is as following:

{
  type: ...,
  payload: ...
}

Action creators

All action creators are pure functions that given payload return an action object:

import { UPDATE_CURRENT_USER } from './actionTypes';
exoprt const updateCurrentUser = user => ({
  type: UPDATE_CURRENT_USER,
  payload: user
});

Besides usual action creators we use functions (bound action creators) that could produce side effects (eg executing asynchronous API call) and eventually dispatch an action. These functions are handled by Redux Thunk middleware when executed.

export const getCurrentUser = () => async dispatch => {
  const response = await api.getCurrentUser();
  dispatch(updateCurrentUser(response.data.user));
};

Reducers

In the begging of every reducer file we declare a variable (an object) that holds an initial state and define its shape:

// users/reducer.js

const initialState = {
	current: {}
};

Also we

  • keep reducers as pure functions
  • don't mutate state object
  • use switch statement to change the state according to provided action type
  • return previous state for the default case:
export const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.UPDATE_CURRENT_USER:
      return {
        ...state,
        current: {
          ...state.current,
          ...action.payload
        }
      };
    default:
      return state;
  }
};