question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using generateRequireSignInWrapper throws error

See original GitHub issue

Using the generateRequireSignInWrapper gives me this error message:

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

Here is my code:

index.js

import React from "react";
import ReactDOM from "react-dom";
import { createStore, applyMiddleware, compose } from "redux";
import { Provider } from "react-redux";
import reduxThunk from "redux-thunk";
import { verifyCredentials } from "./apis/redux-token-auth-config";

import reducers from "./reducers";
import App from "./components/App";

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  reducers,
  composeEnhancers(applyMiddleware(reduxThunk))
);
verifyCredentials(store);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

app.js

import React from "react";
import "semantic-ui-css/semantic.min.css";
import { Router, Route, Switch } from "react-router-dom";
import history from "../history";
import { generateRequireSignInWrapper } from "redux-token-auth";

import LandingPage from "./LandingPage";
import CardCreate from "./CardsCreate";
import CardShow from "./CardShow";
import SignInPage from "./SignInPage";

const requireSignIn = generateRequireSignInWrapper({
  redirectPathIfNotSignedIn: "/signin"
});

const Routes = () => (
  <div className="ui container">
    <Router history={history}>
      <div>
        <Switch>
          <Route path="/" exact component={requireSignIn(LandingPage)} />
          <Route path="/cards/new" exact component={CardCreate} />
          <Route path="/cards/:id" exact component={CardShow} />
          <Route path="/signin" exact component={SignInPage} />
        </Switch>
      </div>
    </Router>
  </div>
);

const App = () => {
  return Routes();
};

export default App;

Issue Analytics

  • State:open
  • Created 5 years ago
  • Comments:7

github_iconTop GitHub Comments

2reactions
Rinbocommented, Feb 24, 2019

@tochman I threw out this module and implemented my own middleware instead:

import axios from "axios";

let HEADERS = ["access-token", "token-type", "client", "expiry", "uid"];

const tokenMiddleware = () => store => next => action => {
  if (!action) {
    action = { type: "" };
  }
  
  let customHeaders = []
  let validateAction = "VALIDATE_TOKEN"
  let logoutAction = "SIGN_OUT"
    
  HEADERS = [...new Set([...HEADERS, ...customHeaders])];
  if (action.type === validateAction) {
    HEADERS.forEach(
      token =>
        (axios.defaults.headers.common[token] = localStorage.getItem(token))
    );
  } else if (action.type === logoutAction) {
    HEADERS.forEach(token => localStorage.removeItem(token));
  } else {
    let { headers } = action;
    if (headers) {
      if (headers["access-token"]) {
        HEADERS.forEach(token => {
          axios.defaults.headers.common[token] = headers[token];
          localStorage.setItem(token, headers[token]);
        });
      }
    }
  }
  return next(action);
};

export default tokenMiddleware;

Then I applied it to store in root index.js:

...
import reduxThunk from "redux-thunk";
import tokenMiddelware from "./tokenMiddleware";

import reducers from "./reducers";
import App from "./components/App";

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

const store = createStore(
  reducers,
  composeEnhancers(applyMiddleware(reduxThunk, tokenMiddelware()))
);
...

Then in authActions i made the following function:

export const validateUser = () => async dispatch => {  
  dispatch({ type: "VALIDATE_TOKEN" });
  const headers = axios.defaults.headers.common;
  try {
    const response = await endpoint.get("api/v1/auth/validate_token", headers);
    const user = response.data.data;
    dispatch(setHeaders(response.headers));
    dispatch({ type: "SIGN_IN", payload: user });
  } catch (err) {
    console.log(err, "Missing Token. Please Log in.");
    dispatch({ type: "LOADED" });
  }
};

The setHeaders function just relays the headers that gets returned from the rails app to the middleware (via the action key), so that they are always available to the axios module (needed for every request).

Then you can make your own custom protected routes (assuming you are using react-router-dom), in which I call the validateUser action in ComponentDidMount. For my part I made three custom routes. AdminRoute, ProtectedRoute (for signed in users) and AuthRoute (which automatically redirects a signed in user away from the signup page). The syntax is a little obscure but here is the ProtectedRoute.js:

import React from "react";
import { Route, Redirect } from "react-router-dom";
import { connect } from "react-redux";
import { validateUser } from "../actions/authActions";

export class ProtectedRoute extends React.Component {
  componentDidMount = () => {
    this.props.validateUser();
  };

  render() {
    const {
      isSignedIn,
      isDOMLoaded,
      component: Component,
      ...rest
    } = this.props;

    if (isDOMLoaded) {
      return (
        <Route
          {...rest}
          render={props =>
            isSignedIn ? (
              <Component {...props} />
            ) : (
              <Redirect
                to={{ pathname: "/auth", state: { from: props.location } }}
              />
            )
          }
        />
      );
    } else {
      return null;
    }
  }
}

const MapStateToProps = state => {
  return {
    isSignedIn: state.currentUser.isSignedIn,
    isDOMLoaded: state.currentUser.isDOMLoaded
  };
};

export default connect(
  MapStateToProps,
  { validateUser }
)(ProtectedRoute);

You can probably omit IsDOMLoaded. Don’t remember why I included that.

Then in your app.js where you define your routes:

import React from "react";
import { Router, Switch, Route } from "react-router-dom";
import history from "../history";

...
import AdminRoute from "./AdminRoute";
import ProtectedRoute from "./ProtectedRoute";
import AuthRoute from "./AuthRoute";
import LandingPage from "./LandingPage";
import Signup from "./auth/Signup";
...

const Routes = () => (
  <div className="ui container">
    <Router history={history}>
      <div>
        <Header />
        <Switch>
          <ProtectedRoute path="/" exact component={LandingPage} />
          <ProtectedRoute path="/profile" exact component={UserProfile} />
          ...
          <AdminRoute path="/admin" exact component={Dashboard} />
          ...     
          <AuthRoute path="/auth" exact component={AuthPage} />
          ...     
        </Switch>
        <Footer />
      </div>
    </Router>
  </div>
);

const App = () => {
  return Routes();
};

export default App;
0reactions
tochmancommented, Mar 5, 2019

Awesome solution.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to Generate Your Own Error Messages in R - dummies
You can tell R to throw an error by inserting the stop() function anywhere in the body of the function, as in the...
Read more >
Issues - redux-token-auth - kylecorbelli - Geeks
Redux actions and reducers to integrate easily with Devise Token Auth - kylecorbelli. ... Using generateRequireSignInWrapper throws error.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found