Quickstart
A quick dive into getting started with Lore
A quick dive into getting started with Lore
In this step we're going to add a logout experience.
You can view the finished code for this step by checking out the
authentication.6
branch of the completed project.
While we don't have a "logout page" in a visual sense, we still have behavior that we want executed when the user logs out, such as removing their user token and redirecting them to the login page.
We're going to store this behavior in a component so that we can have it execute when the user navigates to the /logout
route.
Start by creating a Logout
component:
lore generate component Logout
Then update the Logout
component to look like this:
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import auth from '../utils/auth';
import ShowLoadingScreen from './ShowLoadingScreen';
export default createReactClass({
displayName: 'Logout',
propTypes: {
router: PropTypes.object.isRequired
},
componentDidMount() {
const { router } = this.props;
auth.deleteToken();
router.push('/');
},
render() {
return (
<ShowLoadingScreen/>
);
}
});
import React from 'react';
import PropTypes from 'prop-types';
import auth from '../utils/auth';
import ShowLoadingScreen from './ShowLoadingScreen';
class Logout extends React.Component {
componentDidMount() {
const { router } = this.props;
auth.deleteToken();
router.push('/');
}
render() {
return (
<ShowLoadingScreen/>
);
}
}
Logout.propTypes = {
router: PropTypes.object.isRequired
};
export default Logout;
import React from 'react';
import PropTypes from 'prop-types';
import auth from '../utils/auth';
import ShowLoadingScreen from './ShowLoadingScreen';
class Logout extends React.Component {
static propTypes = {
router: PropTypes.object.isRequired
};
componentDidMount() {
const { router } = this.props;
auth.deleteToken();
router.push('/');
}
render() {
return (
<ShowLoadingScreen/>
);
}
}
export default Logout;
Next import the Logout
component into routes.js
and update the routes to look like this:
// routes.js
...
import Logout from './src/components/Logout';
export default (
<Route>
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
<Route path="/auth/callback" component={AuthCallback} />
...
</Route>
);
Finally, we need to make it so that when the user clicks the Logout
button in the Profile
component they are redirected to the /logout
route, which will delete their user token and redirect them to the login page.
Locate the Logout button in your Profile
component:
// src/components/Profile.js
<button className="btn btn-primary">
Log out
</button>
Convert this button to a React Router Link
and have it point to /logout
:
// src/components/Profile.js
import { Link } from 'react-router';
...
render() {
...
<Link className="btn btn-primary" to="/logout">
Log out
</Link>
...
}
...
With this change in place, clicking the Logout button will redirect you to /logout
, and once you log in, you'll be redirected to the main application.
If everything went well, your application should now look like this.
Below is a list of files modified during this step.
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import auth from '../utils/auth';
import ShowLoadingScreen from './ShowLoadingScreen';
export default createReactClass({
displayName: 'Logout',
propTypes: {
router: PropTypes.object.isRequired
},
componentDidMount() {
const { router } = this.props;
auth.deleteToken();
router.push('/');
},
render() {
return (
<ShowLoadingScreen/>
);
}
});
import React from 'react';
import PropTypes from 'prop-types';
import auth from '../utils/auth';
import ShowLoadingScreen from './ShowLoadingScreen';
class Logout extends React.Component {
componentDidMount() {
const { router } = this.props;
auth.deleteToken();
router.push('/');
}
render() {
return (
<ShowLoadingScreen/>
);
}
}
Logout.propTypes = {
router: PropTypes.object.isRequired
};
export default Logout;
import React from 'react';
import PropTypes from 'prop-types';
import auth from '../utils/auth';
import ShowLoadingScreen from './ShowLoadingScreen';
class Logout extends React.Component {
static propTypes = {
router: PropTypes.object.isRequired
};
componentDidMount() {
const { router } = this.props;
auth.deleteToken();
router.push('/');
}
render() {
return (
<ShowLoadingScreen/>
);
}
}
export default Logout;
import React from 'react';
import { Route, IndexRoute, Redirect } from 'react-router';
/**
* Wrapping the Master component with this decorator provides an easy way
* to redirect the user to a login experience if we don't know who they are.
*/
import UserIsAuthenticated from './src/decorators/UserIsAuthenticated';
/**
* Routes are used to declare your view hierarchy
* See: https://github.com/ReactTraining/react-router/blob/v3/docs/API.md
*/
import Master from './src/components/Master';
import Layout from './src/components/Layout';
import Feed from './src/components/Feed';
import Login from './src/components/Login';
import AuthCallback from './src/components/AuthCallback';
import Logout from './src/components/Logout';
export default (
<Route>
<Route path="/login" component={Login} />
<Route path="/logout" component={Logout} />
<Route path="/auth/callback" component={AuthCallback} />
<Route component={UserIsAuthenticated(Master)}>
<Route path="/" component={Layout}>
<IndexRoute component={Feed} />
</Route>
</Route>
</Route>
);
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import { Link } from 'react-router';
export default createReactClass({
displayName: 'Profile',
propTypes: {
user: PropTypes.object.isRequired
},
getDefaultProps() {
return {
user: {
id: 1,
data: {
nickname: 'ayla',
avatar: 'https://cloud.githubusercontent.com/assets/2637399/19027069/a356e82a-88e1-11e6-87d8-e3e74f55c069.png'
}
}
};
},
render() {
const { user } = this.props;
return (
<div className="card profile">
<div className="card-block">
<img
className="img-circle avatar"
src={user.data.avatar} />
<h4 className="card-title">
Hi {user.data.nickname}!
</h4>
<div className="card-text">
<p>You have permission to perform the following:</p>
<ul className="permissions">
<li>Create Tweets</li>
<li>Edit your own tweets</li>
<li>Delete your own tweets</li>
</ul>
</div>
<Link className="btn btn-primary" to="/logout">
Log out
</Link>
</div>
</div>
);
}
});
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router';
class Profile extends React.Component {
render() {
const { user } = this.props;
return (
<div className="card profile">
<div className="card-block">
<img
className="img-circle avatar"
src={user.data.avatar} />
<h4 className="card-title">
Hi {user.data.nickname}!
</h4>
<div className="card-text">
<p>You have permission to perform the following:</p>
<ul className="permissions">
<li>Create Tweets</li>
<li>Edit your own tweets</li>
<li>Delete your own tweets</li>
</ul>
</div>
<Link className="btn btn-primary" to="/logout">
Log out
</Link>
</div>
</div>
);
}
}
Profile.propTypes = {
user: PropTypes.object.isRequired
};
Profile.defaultProps = {
user: {
id: 1,
data: {
nickname: 'ayla',
avatar: 'https://cloud.githubusercontent.com/assets/2637399/19027069/a356e82a-88e1-11e6-87d8-e3e74f55c069.png'
}
}
};
export default Profile;
import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router';
class Profile extends React.Component {
static propTypes = {
user: PropTypes.object.isRequired
};
static defaultProps = {
user: {
id: 1,
data: {
nickname: 'ayla',
avatar: 'https://cloud.githubusercontent.com/assets/2637399/19027069/a356e82a-88e1-11e6-87d8-e3e74f55c069.png'
}
}
};
render() {
const { user } = this.props;
return (
<div className="card profile">
<div className="card-block">
<img
className="img-circle avatar"
src={user.data.avatar} />
<h4 className="card-title">
Hi {user.data.nickname}!
</h4>
<div className="card-text">
<p>You have permission to perform the following:</p>
<ul className="permissions">
<li>Create Tweets</li>
<li>Edit your own tweets</li>
<li>Delete your own tweets</li>
</ul>
</div>
<Link className="btn btn-primary" to="/logout">
Log out
</Link>
</div>
</div>
);
}
}
export default Profile;
Next we're going to add an endpoint to the mock API that we can use to retrieve the current user.