To be honest I avoided using Context for a long time. I easily began to use hooks, but I did not immediately understand Сontext. In this article I will show you one way to use Context.
const App = () => {
<Switch>
<Route path=”/profile” component={ProfilePage} />
<Route path=”/login” component={LoginPage} />
<Redirect to=”/login” />
</Switch>
};
Let's restrict access to the ProfilePage
- only authenticated users can access this page. If the user is a guest, we redirect him to the login page.
const LoginPage = () => {
const [redirectTo, setRedirectTo] = useState(null);
const submitHandler = e => {
e.preventDefault();
const formData = new FormData(e.target);
authenticate(formData).then(user => {
if (user.authenticated) {
this.setState({ redirectTo: ‘/profile’ });
}
});
}
if (redirectTo) {
return (
<Redirect to={redirectTo} />
);
}
return (
<Form omSubmit={submitHandler}>
<Form.Input required type=”email” name=”email” label=”Email” />
<Form.Input required type=”password” name=”password” label=”Password” />
<Form.Button type=”submit” />
</Form>
);
};
The authenticate
method sends user credentials to the API. When we get a response, we redirect the user to the ProfilePage
. All is well, except for one trifle - everyone can access to the ProfilePage
without authentication. To fix this, we need a flag - a global variable - to indicate whether the user is authenticated or not. Let's create Context that allows us to send a flag to components.
import React, { useState } from ‘react’;
export const AuthContext = React.createContext();
export const AuthProvider = ({ children }) => {
const [authenticated, setAuthenticated] = useState(false);
return (
<AuthContext.Provider value={{authenticated, setAuthenticated}}>
{children}
</AuthContext.Provider>
);
};
export const AuthConsumer = AuthContext.Consumer;
Go to the App.js
file and wrap the Switch
into the AuthProvider
. AuthContext.Provider
allows us to pass the context value - the authenticated
flag and the setAuthenticated
method - to all child components.
import { AuthProvider } from ‘./authContext’;
const App = () => {
<AuthProvider>
<Switch>
<Route path=”/profile” component={ProfilePage} />
<Route path=”/login” component={LoginPage} />
<Redirect to=”/login” />
</Switch>
<AuthProvider>
};
And make changes to the LoginPage
.
import React, { useState, useContext } from ‘react’;
import { AuthContext } from ‘./authContext’;
const LoginPage = () => {
const context = useContext(AuthContext);
const [redirectTo, setRedirectTo] = useState(null);
const submitHandler = e => {
e.preventDefault();
const formData = new FormData(e.target);
authenticate(formData).then(user => {
context.setAuthenticated(true);
Now we just have to subscribe to the changes and send off a guest.
import { AuthConsumer } from ‘./authContext’;
const ProtectedRoute = ({ component: Component, ...rest }) => (
<Route {...rest} render={matchProps => (
<AuthConsumer>
{value => (
<Fragment>
{value.authenticated || (
<Redirect to=”/login” />
)}
<Component {...matchProps} />
</Fragment>
)}
</AuthConsumer>
)} />
);
Consumer is a React component, that subscribes to Context changes. It takes the function as a child and passes the current Context value to it.
Finishing touch.
import { AuthProvider } from ‘./authContext’;
import { ProtectedRoute } from’./ProtectedRoute’;
const App = () => {
<AuthProvider>
<Switch>
<ProtectedRoute path=”/profile” component={ProfilePage} />
<Route path=”/login” component={LoginPage} />
<Redirect to=”/login” />
</Switch>
<AuthProvider>
};
Top comments (0)