Skip to content
This repository has been archived by the owner on Apr 8, 2020. It is now read-only.

React-Redux Issue with StaticRouter, serverside rendering and state.routing #1131

Closed
DanHarman opened this issue Jul 19, 2017 · 6 comments
Closed

Comments

@DanHarman
Copy link
Contributor

Hi,

Issue
When serverside rendering, the store.routing.location is null. This is because serverside is using a StaticRouter rather than a ConnectedRouter so there is nothing ensuring the correct actions are pushed to keep the store in sync.

Result
Serverside rendering any component relying on the location being in the store will find a null object there. This will either cause a null reference exception, or if that is dealt with, a re-render on the client as it will have to handle re-rendering affected components.

Remediation
There are a few ways to do this:

  1. Use connected router on the server. Quick and easy but maybe more expensive than static router?
  2. Manually dispatch the location change so that the routeReducer can fixup the store.
  3. Manually pass the Location into the initial version of the ApplicationState (most efficient), but a bit more coupled to the implementation.

I appreciate maybe this is an edge case, so not sure if you want to address it in the template. Its worth noting that ApplicationState doesn't expose the RouterState unless one adds it in, so I guess most people won't be using this. Then again whats the point of wiring it in, if its not be used!

It's also worth noting that react-router-redux has a bug at the moment where the back button is one step behind for all non-trivial apps without taking extra measures. It doesn't affect the template, but it got me on my more complex app. remix-run/react-router#5072

@DanHarman DanHarman changed the title React-Redux Issue with StaticRouter React-Redux Issue with StaticRouter, serverside rendering and state.routing Jul 19, 2017
@DanHarman
Copy link
Contributor Author

I've got option 3 working if you would accept a pull request. (also option 1, but I presume you were trying to be efficient by using StaticRouter in the first place).

@SteveSandersonMS
Copy link
Member

Thanks for letting us know!

Are you saying that ConnectedRouter would lead to the simplest application code? If so, that's probably what we'd want to use, as it's vital that people can understand what's going on, and is preferable rather than having extra logic in the template.

Would you be interested in posting a PR that enables ConnectedRouter?

I'll closing this pending a PR. Thanks for your help!

@timothywisdom
Copy link

@DanHarman - may I please see your PR regarding this? I have the same problem and would like to see some solutions.

@DanHarman
Copy link
Contributor Author

I never submitted it, but I think it was fixed in the template?

@timothywisdom
Copy link

I don't think it was fixed or perhaps I'm missing something.

I have solved it but I'm not super happy about my solution as I have to call configureStore twice and it seems fragile.

Here I configure the store, capture the initial state into an object, update the initial state with routing information, then configure the store again while passing in the new initial state data.

/*** boot-server.tsx ***/
const memoryHistory = createMemoryHistory();
let store: Store<IApplicationState> = configureStore(memoryHistory);
const initialState: IApplicationState = {
			...store.getState(),
			routing: {
				match: {
					params: {},
					isExact: true,
					path: memoryHistory.location.pathname,
					url: memoryHistory.location.pathname,
				},
				history: memoryHistory,
				location: memoryHistory.location
			}
		}
store = configureStore(memoryHistory, initialState);

I can see these lines in the template:

const basename = params.baseUrl.substring(0, params.baseUrl.length - 1);
const urlAfterBasename = params.url.substring(basename.length);
store.dispatch(replace(urlAfterBasename));

but they don't seem to update the routing section of the store

@neonboxx
Copy link

Does anyone have a working solution to this?

I have an app where on load an ajax call, using an id from the url, is made to the server, and based on the response i want to direct the user to the correct page. Using replace from react-router-redux does not seem to work on the server side. I tried using the connected router in boot-server, this resulted in the page being changed, but the browser URL not being updated. so as soon as the client loads the page changes back...

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants