redux-token-auth
redux-token-auth copied to clipboard
I am receiving weird error regarding GatePage.
Error
Could not find "store" in either the context or props of "Connect(GatedPage)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(GatedPage)".
Main index
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { BrowserRouter } from "react-router-dom";
import "./assets/css/main.scss";
import App from "./App";
import { configureStore } from "./store";
import { verifyCredentials } from "./lib";
import * as serviceWorker from "./utils/serviceWorker";
const store = configureStore();
verifyCredentials(store);
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>,
document.getElementById("root")
);
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
Routes
import React, { Component, Fragment } from "react";
import { Route } from "react-router-dom";
import { generateRequireSignInWrapper } from "redux-token-auth";
import { Home, Login, Protected, SignUp } from "../containers";
import {
ROOT_PATH,
SIGN_IN_PATH,
SIGN_UP_PATH,
PROTECTED_PATH
} from "../constants/routes";
const requireSignIn = generateRequireSignInWrapper({
redirectPathIfNotSignedIn: "/login"
});
export default class Routes extends Component {
render() {
return (
<Fragment>
<Route exact path={ROOT_PATH} component={Home} />
<Route path={PROTECTED_PATH} component={requireSignIn(Protected)} />
<Route path={SIGN_IN_PATH} component={Login} />
<Route path={SIGN_UP_PATH} component={SignUp} />
</Fragment>
);
}
}
Main App container
import React, { Component } from "react";
import { withHead } from "../lib";
import { Layout } from "../components";
import Routes from "../Routes";
class App extends Component {
render() {
return (
<Layout>
<Routes />
</Layout>
);
}
}
export default withHead(App);
Versions
"dependencies": {
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-redux": "^6.0.0",
"react-router-dom": "^4.3.1",
"react-scripts": "2.1.2",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"redux-token-auth": "^0.19.0",
}
+1
I have the same problem. :/
I have the same problem. :/
I couldn't find a solution so ended up developing my own PrivateRoutes setup. Not perfect but does the job. See below my code if that helps.
import React from 'react';
import {Route, Redirect} from 'react-router-dom'
export default function PrivateRoute({ component: Component, authed, ...rest }) {
return (
<Route
{...rest}
render={props =>
authed === true ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
}
import React, {Component} from 'react';
import {Route} from 'react-router-dom'
import { connect } from 'react-redux'
import {withRouter} from 'react-router-dom';
import PrivateRoute from './PrivateRoute'
import Home from './components/Home.js'
import Profile from './components/Users/Profile.js'
import Logout from './components/Users/Logout.js'
class Routes extends Component {
constructor(props){
super(props)
this.state={
auth: this.props.isSignedIn
}
}
componentDidUpdate(prevProps){
if(this.props.isSignedIn !== prevProps.isSignedIn){
this.setState({
auth: this.props.isSignedIn
})
}
}
render(){
return(
<React.Fragment>
<Route exact path="/" component={Home} />
<PrivateRoute authed={this.state.auth} exact path="/profile" component={Profile} />
<PrivateRoute authed={this.state.auth} exact path="/logout" component={Logout} />
</React.Fragment>
)
}
}
function mapStateToProps (state) {
return {
isSignedIn: state.reduxTokenAuth.currentUser.isSignedIn
}
}
export default withRouter(connect(mapStateToProps, null)(Routes));
I have the same problem. :/
I couldn't find a solution so ended up developing my own PrivateRoutes setup. Not perfect but does the job. See below my code if that helps.
import React from 'react'; import {Route, Redirect} from 'react-router-dom' export default function PrivateRoute({ component: Component, authed, ...rest }) { return ( <Route {...rest} render={props => authed === true ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: "/login", state: { from: props.location } }} /> ) } /> ); }
import React, {Component} from 'react'; import {Route} from 'react-router-dom' import { connect } from 'react-redux' import {withRouter} from 'react-router-dom'; import PrivateRoute from './PrivateRoute' import Home from './components/Home.js' import Profile from './components/Users/Profile.js' import Logout from './components/Users/Logout.js' class Routes extends Component { constructor(props){ super(props) this.state={ auth: this.props.isSignedIn } } componentDidUpdate(prevProps){ if(this.props.isSignedIn !== prevProps.isSignedIn){ this.setState({ auth: this.props.isSignedIn }) } } render(){ return( <React.Fragment> <Route exact path="/" component={Home} /> <PrivateRoute authed={this.state.auth} exact path="/profile" component={Profile} /> <PrivateRoute authed={this.state.auth} exact path="/logout" component={Logout} /> </React.Fragment> ) } } function mapStateToProps (state) { return { isSignedIn: state.reduxTokenAuth.currentUser.isSignedIn } } export default withRouter(connect(mapStateToProps, null)(Routes));
Thanks.
you can also just replace the requireSignIn
function by this one:
import React, { useEffect } from 'react'
import { compose } from 'redux'
import { connect } from 'react-redux'
import { withRouter } from 'react-router-dom'
const LOGIN_PATH = '/login'
[...]
const requireSignIn = Component =>
compose(
withRouter,
connect(state => ({ authUser: state.reduxTokenAuth.currentUser })),
)(({ authUser, ...props }) => {
useEffect(() => {
if (!authUser.isSignedIn && !authUser.isLoading) props.history.push(LOGIN_PATH)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [authUser])
return authUser ? <Component {...props} /> : null
})
When using @gtournie solution I found again the race condition of redux-token-auth
and react-router
that redirected me to GatePage
soon before token had been verified. So I decided to stick again to generateRequireSignInWrapper
#35
Briefly, the problem is related to react-redux
version 6 which creates a separated context, then the GatePage
component under this library cannot reach to store, even though Provider
is corrected setup
https://github.com/reduxjs/react-redux/issues/1166#issuecomment-460204182
The problem can be solved if the context is matched, so upgrading react-redux
and its dependencies to match to your main app package.json
can simply fix.
It should be mentioned in the docs. Personally I decide to fork instead of making PR since the author has been inactive
@suyesh Follow https://yarnpkg.com/lang/en/docs/selective-version-resolutions/, Adding this config to your package.json to resolve the issue, I tested and it works
"resolutions": {
"react-redux": "^7.1.1"
},
This config tells redux-token-auth depends on newest react-redux version
React Router (react-router-dom) 5.x
works with history 4.x
. If redirects not working properly or not rendering, downgrade histroy version.