Guest User

Untitled

a guest
May 21st, 2018
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.35 KB | None | 0 0
  1. # react-router 4 basic setup
  2.  
  3. Basic react-router 4 setup for login and protected routes.
  4. Requires the user to log in in order to see those protected routes.
  5.  
  6. * Assuming there is a `UserStore` that performs actual operations (e.g. ajax calls) and provides a `user` prop to components when the user is logged in.
  7. * Omitting any insiginificant import statements. This is not 100% copy-pastable, but still pretty much real-world code
  8.  
  9. ## index.js
  10.  
  11. Renders the `App`, but wrapped in a `Router`. That way we can use `Route` and `Switch` components anywhere in our app tree.
  12.  
  13. ```
  14. import { Router } from 'react-router-dom';
  15. import App from './App';
  16.  
  17. ReactDOM.render(
  18. <Router>
  19. <App />
  20. </Router>,
  21. document.getElementById('root')
  22. );
  23. ```
  24.  
  25. ## App.js
  26.  
  27. Defines the "outline" of our app - a mapping of routes and components.
  28. Note how we use the regular `Route` and the custom `ProtectedRoute`.
  29.  
  30. ```
  31. import { Route, Switch } from 'react-router-dom';
  32. import ProtectedRoute from './ProtectedRoute';
  33.  
  34. export default class App extends Component {
  35. render() {
  36. return (
  37. <div className={cx('App', css.App)}>
  38. <Switch>
  39. <Route path="/login" component={LoginPage} />
  40.  
  41. <ProtectedRoute exact path="/" component={DashboardPage} />
  42. <ProtectedRoute path="/dashboard" component={DashboardPage} />
  43. <ProtectedRoute path="/concept/:conceptID?/:selectedID?" component={ConceptPage} />
  44. <ProtectedRoute path="/settings" component={SettingsPage} />
  45. </Switch>
  46. </div>
  47. );
  48. }
  49. }
  50. ```
  51.  
  52. ## ProtectedRoute.js
  53.  
  54. A special route that will redirect to `/login` unless already logged in.
  55.  
  56. Note how it expects to receive a `user` prop to know whether it's logged in or not.
  57. In this example, it uses a decorator to retrieve the value from a store. The `user` value will be either undefined or an object.
  58. We use the `render` prop of `Route` and decide what to render based the `user` value.
  59.  
  60. ```
  61. import { Route, Redirect } from 'react-router-dom';
  62.  
  63. @connect([
  64. {
  65. store: UserStore,
  66. props: ['user']
  67. }
  68. ])
  69. export default class ProtectedRoute extends PureComponent {
  70. static propTypes = {
  71. user: PropTypes.object,
  72. component: PropTypes.oneOfType([PropTypes.node, PropTypes.element, PropTypes.func])
  73. };
  74. render() {
  75. const { user, component: Component, ...props } = this.props;
  76. return (
  77. <Route
  78. {...props}
  79. render={props => {
  80. if (user) {
  81. return <Component {...props} />;
  82. } else {
  83. return <Redirect to="/login" />;
  84. }
  85. }}
  86. />
  87. );
  88. }
  89. }
  90. ```
  91.  
  92. ## LoginPage.js
  93.  
  94. Displays a login form, keeps user input in its state and finally submits it.
  95. Notice how it expects the `location` and retrieves it using `@withRouter` as a decorator (or alternatively `export default withRouter(LoginPage)`).
  96.  
  97. It uses the `UserStore.login()` method, which will eventually cause the `user` prop to become populated.
  98. That will cause a re-render which will redirect to the originally requested page..
  99.  
  100. ```
  101. import { Redirect, withRouter, Link } from 'react-router-dom';
  102.  
  103. @withRouter
  104. @connect([
  105. {
  106. store: UserStore,
  107. props: ['user']
  108. }
  109. ])
  110. export default class LoginPage extends Component {
  111. static propTypes = {
  112. user: PropTypes.object,
  113. location: PropTypes.shape({
  114. state: PropTypes.shape({
  115. from: PropTypes.string
  116. })
  117. })
  118. };
  119. state = {
  120. username: '',
  121. password: ''
  122. };
  123. render() {
  124. const { user } = this.props;
  125. const { username, password } = this.state;
  126. const { from } = this.props.location.state || { from: { pathname: '/' } };
  127. if (user) {
  128. return <Redirect to={from} />;
  129. }
  130. return (
  131. <div className={cx('Page LoginPage', css.LoginPage)}>
  132. <h3>Login</h3>
  133. <form onSubmit={this.handleSubmit}>
  134. <div>
  135. <label>Username</label>
  136. <input
  137. type="text"
  138. value={username}
  139. onChange={e => this.setState({ username: e.target.value })}
  140. />
  141. </div>
  142. <div>
  143. <label>Password</label>
  144. <input
  145. type="password"
  146. value={password}
  147. onChange={e => this.setState({ password: e.target.value })}
  148. />
  149. </div>
  150. <footer>
  151. <Link to="/register">Register</Link>
  152. <Button onClick={this.handleSubmit} type="submit" disabled={!username || !password}>
  153. Login
  154. </Button>
  155. </footer>
  156. </form>
  157. </div>
  158. );
  159. }
  160. @autobind
  161. handleSubmit(e) {
  162. e.preventDefault();
  163. e.stopPropagation();
  164. this.login();
  165. }
  166. @autobind
  167. login() {
  168. const { username, password } = this.state;
  169. if (!username || !password) return;
  170. UserStore.login({ username, password });
  171. }
  172. }
  173. ```
Add Comment
Please, Sign In to add comment