Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to hydrate redux store after login?

Tags:

reactjs

redux

Basic setup:

1) App is React and Redux,

2) App is served by a front facing NGINX serving static files like html, pictures and of course the app itself. It also forwards all relevant requests (web sockets and/or AJAX) to the back end (phoenix/elixir).

3) Users are required to authenticate. I'm using redux-oidc library, which is client side only and it works fine.

4) After user logs on is when I get hazy on what to do next.

Question(s):

1) I can't send the state along with the first request because I don't know who the user is and, thus, don't know which state to send. Meanwhile application is already booted (empty store created, login component displayed),

2) After user logs on I can't show anything (like user specific nav bar, timeline , mailbox) I have to saturate the store and let react do its job. What approach should I take?

3) Server rendering is out because a) I'm not using Node and rendering react components using chosen framework is messy and complicated at best and b) I won't be able to export the app to NGinx since it only serves static assets and there is no server logic run there. I could, theoretically, get rid of NGinx, have server based login on the API server and send down HTML along with JSON state which could be used to render the app on the client. However, NGinx does not only serve static assets but also load balances few instances and, thus, getting rid of it is not something I want to do.

Any advice would be appreciated.

like image 353
user981375 Avatar asked Jan 06 '17 00:01

user981375


1 Answers

Hydrating the state after the store was created, can be achieved by creating a main reducer that can bypass the top level reducers, and replace the whole state.

Reducers are functions that get the current state, combine it with the payload of an action, and return a new state. Usually the main reducer is a combination of all top reducers using combineReducers, and the state is the combination of state pieces returned by the top level reducers.

However, the main reducer can react to actions directly. If the main reducer receives a certain action (hydrate), instead of calling the combined reducers, it returns the action's payload (the saved state). Other actions are passed to the combined reducers.

const mainReducer = (state = {}, action) => 
    action.type === 'hydrate' ? 
        action.payload // hydrate the state
        : 
        reducers(state, action); // create new state by using combined reducers

Working example:

const { combineReducers, createStore } = Redux;

const people = (state = [], action) => action.type === 'people' ? [...state, action.payload] : state;

const items = (state = [], action) => action.type === 'items' ? [...state, action.payload] : state;

const reducers = combineReducers({
  people,
  items
});

const mainReducer = (state = {}, action) => action.type === 'hydrate' ? action.payload : reducers(state, action);

const store = createStore(mainReducer);

store.subscribe(() => console.log(store.getState()));

store.dispatch({ type: 'people', payload: 5 });
store.dispatch({ type: 'items', payload: 'green' });
store.dispatch({ type: 'hydrate', payload: { 
  people: [20, 30, 50, 100],
  items: ['green', 'yellow', 'red']
}});
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
like image 161
Ori Drori Avatar answered Nov 05 '22 04:11

Ori Drori