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.
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.