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

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

Description

@DanHarman

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

Activity

  1. changed the title [-]React-Redux Issue with StaticRouter[/-] [+]React-Redux Issue with StaticRouter, serverside rendering and state.routing[/+] on Jul 19, 2017
  2. DanHarman commented on Jul 19, 2017

    @DanHarman
    ContributorAuthor

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

  3. SteveSandersonMS commented on Jul 27, 2017

    @SteveSandersonMS
    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!

  4. timothywisdom commented on Dec 18, 2017

    @timothywisdom

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

  5. DanHarman commented on Dec 20, 2017

    @DanHarman
    ContributorAuthor

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

  6. timothywisdom commented on Dec 20, 2017

    @timothywisdom

    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

  7. neonboxx commented on Mar 22, 2018

    @neonboxx

    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 join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions