refactor - use of PureComponents to avoid useless re-rendering

This commit is contained in:
Sam 2019-01-09 12:07:57 +01:00
parent 3fdbca0404
commit 18df5b994a
4 changed files with 312 additions and 303 deletions

View File

@ -320,7 +320,7 @@
"react/no-unknown-property": "error", "react/no-unknown-property": "error",
"react/no-unused-prop-types": "off", "react/no-unused-prop-types": "off",
"react/prefer-es6-class": "error", "react/prefer-es6-class": "error",
"react/prefer-stateless-function": "error", "react/prefer-stateless-function": [1, { "ignorePureComponents": true }],
"react/prop-types": "off", "react/prop-types": "off",
"react/react-in-jsx-scope": "error", "react/react-in-jsx-scope": "error",
"react/react-default-props": "off", "react/react-default-props": "off",

View File

@ -1,176 +1,178 @@
import React from 'react' import React from 'react'
export default function ActivitiesList (props) { export default class ActivitiesFilter extends React.PureComponent {
const { loadActivities, sports, updateParams } = props render() {
return ( const { loadActivities, sports, updateParams } = this.props
<div className="card"> return (
<div className="card-body activity-filter"> <div className="card">
<form onSubmit={event => event.preventDefault()}> <div className="card-body activity-filter">
<div className="form-group"> <form onSubmit={event => event.preventDefault()}>
<label> <div className="form-group">
From: <label>
<input From:
className="form-control col-md" <input
name="from" className="form-control col-md"
onChange={e => updateParams(e)} name="from"
type="date" onChange={e => updateParams(e)}
/> type="date"
</label> />
<label> </label>
To: <label>
<input To:
className="form-control col-md" <input
name="to" className="form-control col-md"
onChange={e => updateParams(e)} name="to"
type="date" onChange={e => updateParams(e)}
/> type="date"
</label> />
</div> </label>
<div className="form-group"> </div>
<label> <div className="form-group">
Sport: <label>
<select Sport:
className="form-control input-lg" <select
name="sport_id" className="form-control input-lg"
onChange={e => updateParams(e)} name="sport_id"
> onChange={e => updateParams(e)}
<option value="" /> >
{sports.map(sport => ( <option value="" />
<option key={sport.id} value={sport.id}> {sports.map(sport => (
{sport.label} <option key={sport.id} value={sport.id}>
</option> {sport.label}
))} </option>
</select> ))}
</label> </select>
</div> </label>
<div className="form-group"> </div>
<label> <div className="form-group">
Distance (km): <label>
<div className="container"> Distance (km):
<div className="row"> <div className="container">
<div className="col-5"> <div className="row">
<input <div className="col-5">
className="form-control" <input
min={0} className="form-control"
name="distance_from" min={0}
onChange={e => updateParams(e)} name="distance_from"
step="1" onChange={e => updateParams(e)}
type="number" step="1"
/> type="number"
</div> />
<div className="col-2 align-middle text-center">to</div> </div>
<div className="col-5"> <div className="col-2 align-middle text-center">to</div>
<input <div className="col-5">
className="form-control" <input
min={0} className="form-control"
name="distance_to" min={0}
onChange={e => updateParams(e)} name="distance_to"
step="1" onChange={e => updateParams(e)}
type="number" step="1"
/> type="number"
/>
</div>
</div> </div>
</div> </div>
</div> </label>
</label> </div>
</div> <div className="form-group">
<div className="form-group"> <label>
<label> Duration:
Duration: <div className="container">
<div className="container"> <div className="row">
<div className="row"> <div className="col-5">
<div className="col-5"> <input
<input className="form-control"
className="form-control" name="duration_from"
name="duration_from" onChange={e => updateParams(e)}
onChange={e => updateParams(e)} pattern="^([0-9]*[0-9]):([0-5][0-9])$"
pattern="^([0-9]*[0-9]):([0-5][0-9])$" placeholder="hh:mm"
placeholder="hh:mm" type="text"
type="text" />
/> </div>
</div> <div className="col-2 align-middle text-center">to</div>
<div className="col-2 align-middle text-center">to</div> <div className="col-5">
<div className="col-5"> <input
<input className="form-control"
className="form-control" name="duration_to"
name="duration_to" onChange={e => updateParams(e)}
onChange={e => updateParams(e)} pattern="^([0-9]*[0-9]):([0-5][0-9])$"
pattern="^([0-9]*[0-9]):([0-5][0-9])$" placeholder="hh:mm"
placeholder="hh:mm" type="text"
type="text" />
/> </div>
</div> </div>
</div> </div>
</div> </label>
</label> </div>
</div> <div className="form-group">
<div className="form-group"> <label>
<label> Average speed (km/h):
Average speed (km/h): <div className="container">
<div className="container"> <div className="row">
<div className="row"> <div className="col-5">
<div className="col-5"> <input
<input className="form-control"
className="form-control" min={0}
min={0} name="ave_speed_from"
name="ave_speed_from" onChange={e => updateParams(e)}
onChange={e => updateParams(e)} step="1"
step="1" type="number"
type="number" />
/> </div>
</div> <div className="col-2 align-middle text-center">to</div>
<div className="col-2 align-middle text-center">to</div> <div className="col-5">
<div className="col-5"> <input
<input className="form-control"
className="form-control" min={0}
min={0} name="ave_speed_to"
name="ave_speed_to" onChange={e => updateParams(e)}
onChange={e => updateParams(e)} step="1"
step="1" type="number"
type="number" />
/> </div>
</div> </div>
</div> </div>
</div> </label>
</label> </div>
</div> <div className="form-group">
<div className="form-group"> <label>
<label> Max speed (km/h):
Max speed (km/h): <div className="container">
<div className="container"> <div className="row">
<div className="row"> <div className="col-5">
<div className="col-5"> <input
<input className="form-control"
className="form-control" min={0}
min={0} name="max_speed_from"
name="max_speed_from" onChange={e => updateParams(e)}
onChange={e => updateParams(e)} step="1"
step="1" type="number"
type="number" />
/> </div>
</div> <div className="col-2 align-middle text-center">to</div>
<div className="col-2 align-middle text-center">to</div> <div className="col-5">
<div className="col-5"> <input
<input className="form-control"
className="form-control" min={0}
min={0} name="max_speed_to"
name="max_speed_to" onChange={e => updateParams(e)}
onChange={e => updateParams(e)} step="1"
step="1" type="number"
type="number" />
/> </div>
</div> </div>
</div> </div>
</div> </label>
</label> </div>
</div> <input
<input className="btn btn-primary btn-lg btn-block"
className="btn btn-primary btn-lg btn-block" onClick={() => loadActivities()}
onClick={() => loadActivities()} type="submit"
type="submit" value="Filter"
value="Filter" />
/> </form>
</form> </div>
</div> </div>
</div> )
) }
} }

View File

@ -4,13 +4,14 @@ import { Link } from 'react-router-dom'
import { getDateWithTZ } from '../../utils' import { getDateWithTZ } from '../../utils'
export default function ActivitiesList (props) { export default class ActivitiesList extends React.PureComponent {
const { activities, sports, user } = props render() {
return ( const { activities, sports, user } = this.props
<div className="card activity-card"> return (
<div className="card-body"> <div className="card activity-card">
<table className="table"> <div className="card-body">
<thead> <table className="table">
<thead>
<tr> <tr>
<th scope="col" /> <th scope="col" />
<th scope="col">Workout</th> <th scope="col">Workout</th>
@ -20,12 +21,12 @@ export default function ActivitiesList (props) {
<th scope="col">Ave. speed</th> <th scope="col">Ave. speed</th>
<th scope="col">Max. speed</th> <th scope="col">Max. speed</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{ sports && activities.map((activity, idx) => ( {sports && activities.map((activity, idx) => (
// eslint-disable-next-line react/no-array-index-key // eslint-disable-next-line react/no-array-index-key
<tr key={idx}> <tr key={idx}>
<td > <td>
<img <img
className="activity-sport" className="activity-sport"
src={sports src={sports
@ -34,11 +35,11 @@ export default function ActivitiesList (props) {
alt="activity sport logo" alt="activity sport logo"
/> />
</td> </td>
<td > <td>
<Link to={`/activities/${activity.id}`}> <Link to={`/activities/${activity.id}`}>
{activity.title} {activity.title}
</Link> </Link>
</td> </td>
<td> <td>
{format( {format(
getDateWithTZ(activity.activity_date, user.timezone), getDateWithTZ(activity.activity_date, user.timezone),
@ -53,9 +54,10 @@ export default function ActivitiesList (props) {
<td className="text-right">{activity.max_speed} km/h</td> <td className="text-right">{activity.max_speed} km/h</td>
</tr> </tr>
))} ))}
</tbody> </tbody>
</table> </table>
</div>
</div> </div>
</div> )
) }
} }

View File

@ -4,136 +4,141 @@ import { Link } from 'react-router-dom'
import { apiUrl } from '../../utils' import { apiUrl } from '../../utils'
class NavBar extends React.PureComponent {
function NavBar(props) { render() {
return ( const { user } = this.props
<header> return (
<nav className="navbar navbar-expand-lg navbar-light bg-light"> <header>
<div className="container"> <nav className="navbar navbar-expand-lg navbar-light bg-light">
<span className="navbar-brand">FitTrackee</span> <div className="container">
<button <span className="navbar-brand">FitTrackee</span>
className="navbar-toggler" <button
type="button" className="navbar-toggler"
data-toggle="collapse" type="button"
data-target="#navbarSupportedContent" data-toggle="collapse"
aria-controls="navbarSupportedContent" data-target="#navbarSupportedContent"
aria-expanded="false" aria-controls="navbarSupportedContent"
aria-label="Toggle navigation" aria-expanded="false"
> aria-label="Toggle navigation"
<span className="navbar-toggler-icon" /> >
</button> <span className="navbar-toggler-icon" />
<div className="collapse navbar-collapse" id="navbarSupportedContent"> </button>
<ul className="navbar-nav mr-auto"> <div
<li className="nav-item"> className="collapse navbar-collapse"
<Link id="navbarSupportedContent"
className="nav-link" >
to={{ <ul className="navbar-nav mr-auto">
pathname: '/',
}}
>
Dashboard
</Link>
</li>
{props.user.isAuthenticated && (
<li className="nav-item"> <li className="nav-item">
<Link <Link
className="nav-link" className="nav-link"
to={{ to={{
pathname: '/activities/history', pathname: '/',
}} }}
> >
Workouts Dashboard
</Link> </Link>
</li> </li>
)} {user.isAuthenticated && (
{props.user.isAuthenticated && ( <li className="nav-item">
<li className="nav-item"> <Link
<Link className="nav-link"
className="nav-link" to={{
to={{ pathname: '/activities/history',
pathname: '/activities/add', }}
}} >
> Workouts
<strong>Add workout</strong> </Link>
</Link> </li>
</li> )}
)} {user.isAuthenticated && (
{/* {props.user.admin && ( */} <li className="nav-item">
{/* <li className="nav-item"> */} <Link
{/* <Link */} className="nav-link"
{/* className="nav-link" */} to={{
{/* to={{ */} pathname: '/activities/add',
{/* pathname: '/admin', */} }}
{/* }} */} >
{/* > */} <strong>Add workout</strong>
{/* Admin */} </Link>
{/* </Link> */} </li>
{/* </li> */} )}
{/* )} */} {/* {user.admin && ( */}
</ul> {/* <li className="nav-item"> */}
<ul className="navbar-nav flex-row ml-md-auto d-none d-md-flex"> {/* <Link */}
{!props.user.isAuthenticated && ( {/* className="nav-link" */}
<li className="nav-item"> {/* to={{ */}
<Link {/* pathname: '/admin', */}
className="nav-link" {/* }} */}
to={{ {/* > */}
pathname: '/register', {/* Admin */}
}} {/* </Link> */}
> {/* </li> */}
Register {/* )} */}
</Link> </ul>
</li> <ul className="navbar-nav flex-row ml-md-auto d-none d-md-flex">
)} {!user.isAuthenticated && (
{!props.user.isAuthenticated && ( <li className="nav-item">
<li className="nav-item"> <Link
<Link className="nav-link"
className="nav-link" to={{
to={{ pathname: '/register',
pathname: '/login', }}
}} >
> Register
Login </Link>
</Link> </li>
</li> )}
)} {!user.isAuthenticated && (
{props.user.picture === true && ( <li className="nav-item">
<img <Link
alt="Avatar" className="nav-link"
src={`${apiUrl}users/${props.user.id}/picture` + to={{
`?${Date.now()}`} pathname: '/login',
className="img-fluid App-nav-profile-img" }}
/> >
)} Login
{props.user.isAuthenticated && ( </Link>
<li className="nav-item"> </li>
<Link )}
className="nav-link" {user.picture === true && (
to={{ <img
pathname: '/profile', alt="Avatar"
}} src={`${apiUrl}users/${user.id}/picture` +
> `?${Date.now()}`}
{props.user.username} className="img-fluid App-nav-profile-img"
</Link> />
</li> )}
)} {user.isAuthenticated && (
{props.user.isAuthenticated && ( <li className="nav-item">
<li className="nav-item"> <Link
<Link className="nav-link"
className="nav-link" to={{
to={{ pathname: '/profile',
pathname: '/logout', }}
}} >
> {user.username}
Logout </Link>
</Link> </li>
</li> )}
)} {user.isAuthenticated && (
</ul> <li className="nav-item">
<Link
className="nav-link"
to={{
pathname: '/logout',
}}
>
Logout
</Link>
</li>
)}
</ul>
</div>
</div> </div>
</div> </nav>
</nav> </header>
</header> )
) }
} }
export default connect( export default connect(