Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

490
Visualizações
How to hydrate redux store after login?

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.

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

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>

over 4 years ago · Santiago Trujillo Relatório

0

Even though the accepted answer might do the trick, I think that what you are chasing is an anti-pattern, after all.

If you are doing client rendering and handling authentication client side, the only thing you should send to your client, in my opinion, is a <Spinner/>, with zero preloaded state.

Once you are on the client, initialise your store, do your authentication, and decide if you are going to fetch data and render the authenticated version of the page, or if user is not authenticated yet, show them the login form. Everything from this point on, should be handled client side.

Here is what Redux has to say about it:

https://redux.js.org/usage/server-rendering

enter image description here

So, if during the initial render you got "Schrödinger" user (might be authenticated or not), the only thing you can safely assume to show is a spinner.


ANOTHER OPTION

If you really need to get new preloaded data from the server on multiple requests (that's kind of what happens in NextJS apps).

If you are going to pre-render every page (and get new state that on every page change), you can do what NextJS suggests you to do:

  • They basically re-initialise the store and merge the new data every time it receives new preloaded data from the server.

Here is the example:

https://github.com/vercel/next.js/tree/canary/examples/with-redux-thunk

And the main part of their code:

import { useMemo } from 'react'
import { createStore, applyMiddleware } from 'redux'
import { composeWithDevTools } from 'redux-devtools-extension'
import thunkMiddleware from 'redux-thunk'
import reducers from './reducers'

let store

function initStore(initialState) {
  return createStore(
    reducers,
    initialState,
    composeWithDevTools(applyMiddleware(thunkMiddleware))
  )
}

export const initializeStore = (preloadedState) => {
  let _store = store ?? initStore(preloadedState)

  // After navigating to a page with an initial Redux state, merge that state
  // with the current state in the store, and create a new store
  if (preloadedState && store) {
    _store = initStore({
      ...store.getState(),
      ...preloadedState,
    })
    // Reset the current store
    store = undefined
  }

  // For SSG and SSR always create a new store
  if (typeof window === 'undefined') return _store
  // Create the store once in the client
  if (!store) store = _store

  return _store
}

export function useStore(initialState) {
  const store = useMemo(() => initializeStore(initialState), [initialState])
  return store
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda