...
/Utilising ImmutableJS for top performance
Utilising ImmutableJS for top performance
Let's roll up our sleeves and apply our learnings from ImmutableJS to our React/Redux weather app.
We'll cover the following...
As a short experiment, try putting a console.log('RENDER PLOT')
into the render
method of the Plot
component:
class Plot extends React.Component {
/* … */
render() {
console.log('RENDER PLOT');
return (
<div id="plot" ref="plot"></div>
);
}
}
Now try using the app for a bit, clicking around, request data for different cities. What you might notice is that the Plot
rerenders even if we only change the location field and the plot itself stays the exact same! (Look at your browser console).
import React from 'react'; import './App.css'; import { connect } from 'react-redux'; import Plot from './Plot'; import { changeLocation, setData, setDates, setTemps, setSelectedDate, setSelectedTemp, fetchData } from './actions'; class App extends React.Component { fetchData = (evt) => { evt.preventDefault(); var location = encodeURIComponent(this.props.location); var urlPrefix = 'https://api.openweathermap.org/data/2.5/forecast?q='; var urlSuffix = '&APPID=dbe69e56e7ee5f981d76c3e77bbb45c0&units=metric'; var url = urlPrefix + location + urlSuffix; this.props.dispatch(fetchData(url)); }; onPlotClick = (data) => { if (data.points) { var number = data.points[0].pointNumber; this.props.dispatch(setSelectedDate(this.props.dates[number])); this.props.dispatch(setSelectedTemp(this.props.temps[number])) } }; changeLocation = (evt) => { this.props.dispatch(changeLocation(evt.target.value)); }; render() { var currentTemp = 'not loaded yet'; if (this.props.data.list) { currentTemp = this.props.data.list[0].main.temp; } return ( <div> <h1>Weather</h1> <form onSubmit={this.fetchData}> <label>City, Country <input placeholder={"City, Country"} type="text" value={this.props.location} onChange={this.changeLocation} /> </label> </form> {/* Render the current temperature and the forecast if we have data otherwise return null */} {(this.props.data.list) ? ( <div> {/* Render the current temperature if no specific date is selected */} {(this.props.selected.temp) ? ( <p>The temperature on { this.props.selected.date } will be { this.props.selected.temp }°C</p> ) : ( <p>The current temperature is { currentTemp }°C!</p> )} <h2>Forecast</h2> <Plot xData={this.props.dates} yData={this.props.temps} onPlotClick={this.onPlotClick} type="scatter" /> </div> ) : null} </div> ); } } // Since we want to have the entire state anyway, we can simply return it as is! function mapStateToProps(state) { return state.toJS(); } export default connect(mapStateToProps)(App);
This is a react feature, react rerenders your entire app whenever something changes. This doesn’t necessarily have a massive performance impact on our current application, but it’ll definitely bite you in a production application! So, what can we do against that?
shouldComponentUpdate
React ...