-
-
Save ryanflorence/eba97731b5579a1c01702c9d394b3feb to your computer and use it in GitHub Desktop.
let UserContext = React.createContext(); | |
class App extends React.Component { | |
state = { | |
user: null, | |
setUser: user => { | |
this.setState({ user }); | |
} | |
}; | |
render() { | |
return ( | |
<UserContext.Provider value={this.state}> | |
<Router> | |
<Home path="/" /> | |
<About path="/about" /> | |
<PrivateRoute as={Dashboard} path="/dashboard" /> | |
</Router> | |
</UserContext.Provider> | |
); | |
} | |
} | |
class PrivateRoute extends React.Component { | |
static contextType = UserContext; | |
render() { | |
let { as: Comp, ...props } = this.props; | |
return this.context.user ? <Comp {...props} /> : <Login />; | |
} | |
} | |
class Login extends React.Component { | |
static contextType = UserContext; | |
render() { | |
return ( | |
<form | |
onSubmit={async () => { | |
let user = await doWhateverYouNeedToDoToLogin(); | |
this.context.setUser(user); | |
}} | |
/> | |
); | |
} | |
} | |
function Home() { | |
return <div>home</div>; | |
} | |
function About() { | |
return <div>about</div>; | |
} | |
function Dashboard() { | |
return <div>Protected dashboard</div>; | |
} |
this is how I implemented PrivateRoute
const PrivateRoute = props => {
const { user } = useUserContext();
let { as: Comp, ...otherProps } = props;
return user ? (
<Comp {...otherProps} />
) : (
<Redirect to="/login" replace={true} noThrow={true} />
);
};
Make sure noThrow
props is set to true
otherwise you'll get exception when redirecting in development.
@christensen143 I like your hooks example but think
// PrivateRoute.js const PrivateRoute = props => { const { user } = useContext(AuthContext); let { as: Comp, ...props } = props; return user ? <Comp {...props} /> : <Login />; }
Should be
// PrivateRoute.js
const PrivateRoute = props => {
const { user } = useContext(AuthContext);
let { as: Comp, ...restOfTheProps } = props;
return user ? <Comp {...restOfTheProps } /> : <Login />;
}
to avoid an Identifier 'props' has already been declared
error.
Make sure noThrow props is set to true otherwise you'll get exception when redirecting in development.
@cvrajeesh you fixed my problem. thank you!
For the people that show up here for how to do this with nested routing, I solved it using nested routers:
// App.js
<Router>
<Login path="/login" />
<ForgotPass path="/forgot-password" />
<PrivateRoute as={Dashboard} path="/dashboard/*" />
</Router>
// Dashboard
export default ({children}) => (
<Router>
<DashHome path="/" />
<DashStatistics path="/statistics" />
</Router>
)
New to this. My <Router>
moans that I don't have path
as a prop in the children components I pass. What happens when you have dynamically created pages (like blog posts) in your gatsby-node.js
? Can't I just have...
<Router>
{authenticated && <PrivateRoute/>}
{!authenticated && <PublicRoute/>}
</Router>
...and then not have to think about it further down the component tree? Rather than pepper my whole application with <Component path="path/to/something"/>
?
Also, does <Router/>
effectively stop Gatsby from serving static files?
@joaodlf