Skip to content

Instantly share code, notes, and snippets.

@rickyhaswifi
Last active October 2, 2019 01:51
Show Gist options
  • Save rickyhaswifi/f2c4e6dabe203042b3fb71cac34e72b9 to your computer and use it in GitHub Desktop.
Save rickyhaswifi/f2c4e6dabe203042b3fb71cac34e72b9 to your computer and use it in GitHub Desktop.
React Authentication - Devise/Rails
import React from 'react';
import { Switch, Route } from 'react-router-dom';
import { Container } from 'semantic-ui-react';
import Navbar from './components/shared/Navbar';
import Home from './components/shared/Home';
import Nomatch from './components/shared/Nomatch';
import Login from './components/auth/Login';
import Register from './components/auth/Register';
import FetchUser from './components/auth/FetchUser';
const App = () => (
<>
<Navbar />
<FetchUser>
<Container>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/login' component={Login} />
<Route exact path='/register' component={Register} />
<Route component={Nomatch} />
</Switch>
</Container>
</FetchUser>
</>
)
export default App;
import React, { Component } from 'react';
import axios from 'axios';
import { AuthConsumer } from '../../providers/AuthProvider';
class FetchUser extends Component {
state = { loaded: false }
componentDidMount() {
const { auth: { authenticated, setUser } } = this.props
if (authenticated) {
this.loaded();
} else {
if (this.checkLocalToken()) {
axios.get('/api/auth/validate_token')
.then( res => {
setUser(res.data.data)
this.loaded()
})
.catch( res => {
this.loaded()
})
} else {
this.loaded()
}
}
}
checkLocalToken = () => {
const token = localStorage.getItem('access-token')
return token
}
loaded = () => this.setState({ loaded: true })
render() {
return this.state.loaded ? this.props.children : null
}
}
const ConnectedFetchUser = (props) => (
<AuthConsumer>
{ auth =>
<FetchUser { ...props } auth={auth} />
}
</AuthConsumer>
)
export default ConnectedFetchUser;
import React from 'react';
import { AuthConsumer, } from "../../providers/AuthProvider";
import { Button, Form, Segment, Header, } from 'semantic-ui-react';
class Login extends React.Component {
state = { email: '', password: '' }
handleSubmit = (e) => {
e.preventDefault();
const { email, password, } = this.state;
this.props.auth.handleLogin({ email, password, }, this.props.history);
}
handleChange = (e) => {
const { name, value, } = e.target;
this.setState({ [name]: value, });
}
render() {
const { email, password, } = this.state;
return (
<Segment basic>
<Header as='h1' textAlign='center'>Login</Header>
<Form onSubmit={this.handleSubmit}>
<Form.Input
label="Email"
autoFocus
required
name='email'
value={email}
placeholder='Email'
onChange={this.handleChange}
/>
<Form.Input
label="Password"
required
name='password'
value={password}
placeholder='Password'
type='password'
onChange={this.handleChange}
/>
<Segment textAlign='center' basic>
<Button primary type='submit'>Submit</Button>
</Segment>
</Form>
</Segment>
)
}
}
export default class ConnectedLogin extends React.Component {
render() {
return (
<AuthConsumer>
{ auth => <Login {...this.props} auth={auth} />}
</AuthConsumer>
)
}
}
import React from 'react'
import { AuthConsumer, } from "../../providers/AuthProvider";
import { Menu, } from 'semantic-ui-react'
import { Link, withRouter, } from 'react-router-dom'
class Navbar extends React.Component {
rightNavItems = () => {
const { auth: { user, handleLogout, }, location, } = this.props;
if (user) {
return (
<Menu.Menu position='right'>
<Menu.Item
name='logout'
onClick={ () => handleLogout(this.props.history) }
/>
</Menu.Menu>
)
} else {
return (
<Menu.Menu position='right'>
<Link to='/login'>
<Menu.Item
id='login'
name='login'
active={location.pathname === '/login'}
/>
</Link>
<Link to='/register'>
<Menu.Item
id='register'
name='register'
active={location.pathname === '/register'}
/>
</Link>
</Menu.Menu>
)
}
}
render() {
return (
<div>
<Menu pointing secondary>
<Link to='/'>
<Menu.Item
name='home'
id='home'
active={this.props.location.pathname === '/'}
/>
</Link>
{ this.rightNavItems() }
</Menu>
</div>
)
}
}
export class ConnectedNavbar extends React.Component {
render() {
return (
<AuthConsumer>
{ auth =>
<Navbar { ...this.props } auth={auth} />
}
</AuthConsumer>
)
}
}
export default withRouter(ConnectedNavbar);
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { AuthConsumer } from '../../providers/AuthProvider';
const ProtectedRoute = ({component: Component, ...rest }) => (
<AuthConsumer>
{ auth =>
<Route
{...rest}
render={ props => (
auth.authenticated ?
<Component {...props} />
:
<Redirect
to={{
pathname: "/login",
state: { from: props.location}
}}
/>
)}
/>
}
</AuthConsumer>
)
export default ProtectedRoute;
import React from 'react';
import { AuthConsumer, } from "../../providers/AuthProvider";
import { Button, Form, Segment, Header, } from 'semantic-ui-react';
class Register extends React.Component {
state = { email: '', password: '', passwordConfirmation: '', };
handleSubmit = (e) => {
e.preventDefault();
const { email, password, passwordConfirmation } = this.state;
const { auth: { handleRegister, }, history, } = this.props;
if (password === passwordConfirmation)
handleRegister({ email, password, passwordConfirmation, }, history);
else
alert('Passwords Do Not Match!')
}
handleChange = (e) => {
const { name, value, } = e.target;
this.setState({ [name]: value, });
}
render() {
const { email, password, passwordConfirmation, } = this.state;
return (
<Segment basic>
<Header as='h1' textAlign='center'>Register</Header>
<Form onSubmit={this.handleSubmit}>
<Form.Input
label="Email"
required
autoFocus
name='email'
value={email}
placeholder='Email'
onChange={this.handleChange}
/>
<Form.Input
label="Password"
required
name='password'
value={password}
placeholder='Password'
type='password'
onChange={this.handleChange}
/>
<Form.Input
label="Password Confirmation"
required
name='passwordConfirmation'
value={passwordConfirmation}
placeholder='Password Confirmation'
type='password'
onChange={this.handleChange}
/>
<Segment textAlign='center' basic>
<Button primary type='submit'>Submit</Button>
</Segment>
</Form>
</Segment>
)
}
}
export default class ConnectedRegister extends React.Component {
render() {
return (
<AuthConsumer>
{ auth => <Register { ...this.props } auth={auth} /> }
</AuthConsumer>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment