Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I am receiving weird error regarding GatePage. #56

Open
suyesh opened this issue Dec 26, 2018 · 8 comments
Open

I am receiving weird error regarding GatePage. #56

suyesh opened this issue Dec 26, 2018 · 8 comments

Comments

@suyesh
Copy link

suyesh commented Dec 26, 2018

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",
  }
@antonwestman
Copy link

+1

@allefgomes
Copy link

I have the same problem. :/

@Bechev
Copy link

Bechev commented Apr 14, 2019

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

@allefgomes
Copy link

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.

@gtournie
Copy link

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

@keymastervn
Copy link

keymastervn commented Sep 11, 2019

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

reduxjs/react-redux#1166 (comment)

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

@tropicalwhite
Copy link

tropicalwhite commented Oct 8, 2019

@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

@mawais786
Copy link

React Router (react-router-dom) 5.x works with history 4.x. If redirects not working properly or not rendering, downgrade histroy version.

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

No branches or pull requests

8 participants