1

How can one persist the full router history of a user visiting an SSR react-redux app? I have tried modifying the react-redux-router package's reducer.js file as such...but when the user loads via SSR, the history array is reset.

/**
 * This action type will be dispatched when your history
* receives a location change.
   */
export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE'

 const initialState = {
    locationBeforeTransitions: null,
    locationHistory: []
}

/**
 * This reducer will update the state with the most recent location history 
 * has transitioned to. This may not be in sync with the router,     particularly
 * if you have asynchronously-loaded routes, so reading from and relying on
 * this state is discouraged.
 */
 export function routerReducer(state = initialState, { type, payload } = {})         {
 if (type === LOCATION_CHANGE) {

return { ...state,
  locationBeforeTransitions: payload,
  locationHistory: state.locationHistory.concat([payload]) }
 }

return state
}

ref: https://github.com/reactjs/react-router-redux/blob/master/src/reducer.js

However, I think this is supposed to be achieved in a middleware.

Irregardless, this (storing the entire previous session history) seems like a common enough use case that perhaps someone has already formulated a best practice.??

Perhaps even this full history is accessible via the historyjs object in react-router w/o react-router-redux.

I'm looking for answers to how to fulfill storing the full history of a user's session in the redux state and post it to my api server when the user closes the browser or navigates away from the site. (if this is not possible, i could just post it upon every navigation.) Then I would like to show this history in a 'recently viewed' list of pages on the users' home pages.

1 Answer 1

0

First of all, you don't have to meddle with the internals of react-redux-router.

As you can see in the code you presented, react-redux-router exports a LOCATION_CHANGE action.

You can use this action in a reducer of your own. Here's an example:

// locationHistoryReducer.js
import { LOCATION_CHANGE } from 'react-router-redux';

export default function locationHistory(state = [], action) {
  if (action.type === LOCATION_CHANGE) {
    return state.concat([action.payload]);
  }
  return state;
}

However, this may be unnecessary. Your assumption that this can be be achieved with middleware is correct. Here's an example of a middleware layer:

const historySaver = store => next => action => {
  if (action.type === LOCATION_CHANGE) {
    // Do whatever you wish with action.payload
    // Send it an HTTP request to the server, save it in a cookie, localStorage, etc.
  }
  return next(action)
}

And here's how to apply that layer in the store:

let store = createStore(
  combineReducers(reducers),
  applyMiddleware(
    historySaver
  )
)

Now, how you save and load data is entirely up to you (and has nothing to do with react-router and the browser's history).

In the official docs, they recommend injecting the initial state on the server side using a window.__PRELOADED_STATE__ variable.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.