Reactlandia
Published in

Reactlandia

Server-Render like a Pro /w Redux-First Router in 10 steps

1. SETUP EXPRESS TO SERVE YOUR BUILD

server/index.js

2. SETUP 2 WEBPACK CONFIGS (SERVER + CLIENT)

client config / server config

3. renderToString

server/render.js
  • configure your store (we’ll get to that soon)
  • render your app to string
  • prepare you state for rehydration on the client by converting it to a JSON string
  • send the basics to the client

Part 2: server/configureStore.js

4. thunk: data-fetching

server/configureStore.js
  1. Create your in-memory history using the request path visited as the one and only entry. The history object will live and die with a single request.
  2. pass the history to the same configureStore you use on the client
  3. receive your store and thunk (we'll see why that's returned soon)
  4. await on the the thunk
  5. set the status based on the location.type state
  • Redux middleware is not async
  • it allows you to do custom work before + after, as you’ll see below
src/configureStore.js
src/routesMap.js

Part 3

5. REDIRECTS (onBeforeChange)

server/configureStore.js (modified)
server/render.js

How do you create redirects in the first place?

options.js — redirect is simple action creator built into RFR

6. REDIRECTS (route-level)

src/routesMap.js
src/routesMap.js

7. REDIRECTS (OPTIMIZE)

server/configureStore.js
  1. The first redirect will be caused by onBeforeChange, for example detecting the user is not allowed.
  2. The second redirect will be detected as a result of the thunk resolving.

8. FETCH APP-WIDE DATA

server/configureStore.js
  1. If the route thunk depends on the app-wide thunks, put the route thunk after
  2. if the app-wide thunk depends on the route thunk, put the app-wide thunk after
  3. if neither are dependent on each other, wrap em in a single Promise.all

9. JSON Web Token in preLoaded state

server/configureStore.js
src/options.js
  • If there is no user, you redirect to the LOGIN route
  • if there is a user, but there wasn’t one until now (which will always be the case on the server), dispatch an action to populate the store with the discovered user. Keep in mind this will happen before any route actions are dispatched, which means they will be able to make use of this user data.
src/reducers/user.js

How do we actually get the user from the JSON Web Token?

src/selectors/userFromState.js
arbitrary key/val on route object
  • get the user on either the server or client
  • get any required roles for the current route
  • if there is no role, return the user whose truthy value will indicate the user has permission to view the route
  • If there’s no user, return null
  • if there is a role for the route, return the user if the user has that role
  1. createStore(rootReducer, preloadedState, enhancers) will start out with just the JWT via preloadedState
  2. and end up /w a user object before your route thunks have a chance to resolve, allowing them to determine what to fetch + what state to trigger
  3. OR the user will be redirected to the LOGIN route ⛩

10. TRADITIONAL USER COOKIE STRATEGY

server/configureStore.js
  1. we are using a non-RFR thunk fetchUser to get the user’s info and store it in Redux state based on the sessionId cookie
  2. we are delaying the initial dispatch until after we potentially have the user in state, so that proper filtering (global or route level) can occur.
src/configureStore.js

CONCLUSION

It’s really quite a powerful mechanism — it means you virtually have no server code outside of the Redux/React code you’re already using on the client.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store