简体   繁体   中英

React Router V4 protected private route with Redux-persist and React-snapshot

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()? '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.

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?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM