16

I'm implementing private route like so using React Router Route Component:

function PrivateRoute({component: Component, authed, emailVerified, ...rest}) {
  return (
    <Route
      {...rest}
      render={props =>
        authed === true
          ? <Component {...props} />
          : <Redirect to={{pathname: '/', state: {from: props.location}}} />}/>
  )
}

Expected Behavior:

authed is persisted through page refresh through using redux-persist So on page refresh or reload, if authed prop is true then router should render <Component /> without ever going to path "/"

Actual Behavior which is the Problem:

With authed === true (persisted) reloading the page or refreshing it leads to the following actions taking place(checked redux devtools) the action: "@@router/LOCATION_CHANGE" runs and takes it to the correct secure route but then "@@router/LOCATION_CHANGE" runs again and it redirects to "/" for a moment and finally "@@router/LOCATION_CHANGE" runs again and directs route back to the secure path, even though authed === true through all this in the redux devtools

Then: My guess was that this error has something to with my main App Component rendering before redux-persist has time to re-hydrate the Redux store.

So I tried doing the following:

I tried delaying my main App component render until my store is re-hydrated using redux-persist like so:

  render() {
    const {authed, authedId, location, rehydrationComplete} = this.props
    return (
      <div>
      { rehydrationComplete
       ? <MainContainer>
          <Switch key={location.key} location={location}>
            <Route exact={true} path='/' component={HomeContainer} />
            <Route render={() => <h2> Oops. Page not found. </h2>} />
          </Switch>
      </MainContainer>
      : <div>...Loading </div> }
      </div>
    )
  }

This effectively fixes the issue above of the path changing when "@@router/LOCATION_CHANGE" action runs(only Changes the path keys), However this leads to another Issue with React-snapshot Now: all the static generated html files from react-snapshot Now contain only ...Loading. I tried to set snapshotDelay of 8200 in the react-snapshot options but that didnt solve the issue.

Then: I tried the following to delay React-snapshot call so that it renders html after the store has been rehydrated:

import {render as snapshotRender} from 'react-snapshot'
import {ConnectedRouter} from 'react-router-redux'

async function init() {
const store = await configureStore()
snapshotRender(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  document.getElementById('root')
)

registerServiceWorker()
}

init()

But now i get the error: that 'render' from react-snapshot was never called. Did you replace the call to ReactDOM.render()?

I know this is a loaded question, but I want to effectively use these 3 libs(React-Router V4, Redux-persist, React-snapshot) together to serve protected routes without the mentioned errors.

jasan
  • 11,475
  • 22
  • 57
  • 97
  • Hi @jasan, do you have any shell project we can use as a base? I feel that I'm missing a few pieces there. – rdarioduarte Oct 02 '17 at 18:46
  • @R.DarioDuarte any update? – jasan Oct 03 '17 at 23:28
  • sadly not yet, I attempt to take another approach like using callbacks instead of async await, but get same issue as you. Let you know if I get to something – rdarioduarte Oct 04 '17 at 12:25
  • @jasan have you tried to use `PersistGate` they [recommend in docs](https://www.npmjs.com/package/redux-persist#usage) ? – Tomasz Mularczyk Jan 04 '18 at 19:42
  • I couldn't solve the issue using react-snapshot but I'm now successfully using react-snap lib which uses puppeteer github.com/stereobooster/react-snap – jasan Jan 05 '18 at 00:42
  • @jasan I have a different approach to this problem. Instead of making router with auth aware features, you can make pages aware of auth. Namely, you can specify granularity of auth within a generic container shared across your pages. If you like this i can add more info too.. – mcku Feb 10 '18 at 09:27

1 Answers1

0

I have something similar to you. Here I use React-Router V4 and a persist-like library.

Your router/routes doesn't need to be aware of the persist. They should rely on your redux's store. The persist should rehydrate your store with all the data.

I didn't see where you are using the PrivateRoute component in your example. Where is it?

Arthur Almeida
  • 568
  • 2
  • 8