1.14 State Update
Are we finally done? Even if the user changes several condition values, the difference value of the vehicle model does not change properly.
So far, we’ve only updated a part of our app’s status each time an event occurs.
this.setState({ config });
Now let’s change the carstats
state whenever the config state value changes.
statsUpdate() {const carModels = ['60', '60D', '75', '75D', '90D', 'P100D'];// Fetch model info from BatteryService and calculate then update statethis.setState({carstats: this.calculateStats(carModels, this.state.config)})}
Now we create a function that take the carModels
and the current state value as inputs and reflects the changed carStats
in the app state and pass it to this.setState
as a callback.
By doing this, it is possible to update the config
object first in setState()
, which operates asynchronous method, and to render the changed stats
on the screen based on this.
this.setState({ config }, () => {this.statsUpdate()});
This completes all the puzzles. The complete code for TeslaBattery is:
import React from 'react';import './TeslaBattery.css';import TeslaNotice from '../components/TeslaNotice/TeslaNotice';import TeslaCar from '../components/TeslaCar/TeslaCar';import TeslaStats from '../components/TeslaStats/TeslaStats';import TeslaCounter from '../components/TeslaCounter/TeslaCounter';import TeslaClimate from '../components/TeslaClimate/TeslaClimate';import TeslaWheels from '../components/TeslaWheels/TeslaWheels';import { getModelData } from '../services/BatteryService';class TeslaBattery extends React.Component {constructor(props) {super(props);this.calculateStats = this.calculateStats.bind(this);this.statsUpdate = this.statsUpdate.bind(this);this.increment = this.increment.bind(this);this.decrement = this.decrement.bind(this);this.updateCounterState = this.updateCounterState.bind(this);this.handleChangeClimate = this.handleChangeClimate.bind(this);this.handleChangeWheels = this.handleChangeWheels.bind(this);this.state = {carstats: [],config: {speed: 55,temperature: 20,climate: true,wheels: 19}}}calculateStats = (models, value) => {const dataModels = getModelData();return models.map(model => {const { speed, temperature, climate, wheels } = value;const miles = dataModels[model][wheels][climate ? 'on' : 'off'].speed[speed][temperature];return {model,miles};});}statsUpdate() {const carModels = ['60', '60D', '75', '75D', '90D', 'P100D'];// Fetch model info from BatteryService and calculate then update statethis.setState({carstats: this.calculateStats(carModels, this.state.config)})}componentDidMount() {this.statsUpdate();}updateCounterState(title, newValue) {const config = { ...this.state.config };// update config state with new valuetitle === 'Speed' ? config['speed'] = newValue : config['temperature'] = newValue;// update our statethis.setState({ config }, () => {this.statsUpdate()});}increment(e, title) {e.preventDefault();let currentValue, maxValue, step;const { speed, temperature } = this.props.counterDefaultVal;if (title === 'Speed') {currentValue = this.state.config.speed;maxValue = speed.max;step = speed.step;} else {currentValue = this.state.config.temperature;maxValue = temperature.max;step = temperature.step;}if (currentValue < maxValue) {const newValue = currentValue + step;this.updateCounterState(title, newValue);}}decrement(e, title) {e.preventDefault();let currentValue, minValue, step;const { speed, temperature } = this.props.counterDefaultVal;if (title === 'Speed') {currentValue = this.state.config.speed;minValue = speed.min;step = speed.step;} else {currentValue = this.state.config.temperature;minValue = temperature.min;step = temperature.step;}if (currentValue > minValue) {const newValue = currentValue - step;this.updateCounterState(title, newValue);}}// handle aircon & heating click event handlerhandleChangeClimate() {const config = {...this.state.config};config['climate'] = !this.state.config.climate;this.setState({ config }, () => {this.statsUpdate()});}// handle Wheels click event handlerhandleChangeWheels(size) {const config = {...this.state.config};config['wheels'] = size;this.setState({ config }, () => {this.statsUpdate()});}render() {const { config, carstats } = this.state;return (<form className="tesla-battery"><h1>Range Per Charge</h1><TeslaCar wheelsize={config.wheels} /><TeslaStats carstats={carstats} /><div className="tesla-controls cf"><TeslaCountercurrentValue={this.state.config.speed}initValues={this.props.counterDefaultVal.speed}increment={this.increment}decrement={this.decrement}/><div className="tesla-climate-container cf"><TeslaCountercurrentValue={this.state.config.temperature}initValues={this.props.counterDefaultVal.temperature}increment={this.increment}decrement={this.decrement}/><TeslaClimatevalue={this.state.config.climate}limit={this.state.config.temperature > 10}handleChangeClimate={this.handleChangeClimate}/></div><TeslaWheelsvalue={this.state.config.wheels}handleChangeWheels={this.handleChangeWheels}/></div><TeslaNotice /></form>)}}export default TeslaBattery;
export function getModelData() { return { '60': { 19: { on: { speed: { 45: { '-10': 224, '0': 255, '10': 287, '20': 289, '30': 287, '40': 258 }, 50: { '-10': 211, '0': 238, '10': 264, '20': 267, '30': 267, '40': 244 }, 55: { '-10': 198, '0': 221, '10': 242, '20': 246, '30': 245, '40': 228 }, 60: { '-10': 184, '0': 204, '10': 222, '20': 225, '30': 226, '40': 212 }, 65: { '-10': 170, '0': 187, '10': 202, '20': 206, '30': 208, '40': 195 }, 70: { '-10': 156, '0': 172, '10': 185, '20': 189, '30': 190, '40': 179 }, } }, off: { speed: { 45: { '-10': 297, '0': 312, '10': 318, '20': 325, '30': 329, '40': 333 }, 50: { '-10': 269, '0': 283, '10': 288, '20': 294, '30': 298, '40': 304 }, 55: { '-10': 245, '0': 256, '10': 261, '20': 267, '30': 269, '40': 277 }, 60: { '-10': 221, '0': 231, '10': 236, '20': 242, '30': 243, '40': 252 }, 65: { '-10': 200, '0': 209, '10': 214, '20': 219, '30': 222, '40': 230 }, 70: { '-10': 181, '0': 189, '10': 194, '20': 199, '30': 202, '40': 209 }, } } }, 21: { on: { speed: { 45: { '-10': 220, '0': 251, '10': 283, '20': 285, '30': 282, '40': 284 }, 50: { '-10': 208, '0': 234, '10': 260, '20': 262, '30': 262, '40': 240 }, 55: { '-10': 194, '0': 216, '10': 238, '20': 241, '30': 240, '40': 224 }, 60: { '-10': 180, '0': 199, '10': 217, '20': 220, '30': 221, '40': 208 }, 65: { '-10': 166, '0': 183, '10': 198, '20': 202, '30': 203, '40': 191 }, 70: { '-10': 152, '0': 167, '10': 180, '20': 184, '30': 185, '40': 174 }, } }, off: { speed: { 45: { '-10': 292, '0': 307, '10': 314, '20': 320, '30': 324, '40': 328 }, 50: { '-10': 265, '0': 278, '10': 283, '20': 289, '30': 293, '40': 298 }, 55: { '-10': 240, '0': 251, '10': 256, '20': 261, '30': 264, '40': 272 }, 60: { '-10': 217, '0': 226, '10': 231, '20': 236, '30': 238, '40': 247 }, 65: { '-10': 196, '0': 204, '10': 209, '20': 214, '30': 217, '40': 225 }, 70: { '-10': 177, '0': 184, '10': 189, '20': 194, '30': 197, '40': 204 }, } } } }, '60D': { 19: { on: { speed: { 45: { '-10': 227, '0': 258, '10': 291, '20': 293, '30': 292, '40': 264 }, 50: { '-10': 215, '0': 242, '10': 269, '20': 271, '30': 272, '40': 250 }, 55: { '-10': 201, '0': 224, '10': 247, '20': 250, '30': 251, '40': 235 }, 60: { '-10': 187, '0': 207, '10': 226, '20': 229, '30': 232, '40': 217 }, 65: { '-10': 172, '0': 191, '10': 207, '20': 211, '30': 213, '40': 201 }, 70: { '-10': 158, '0': 175, '10': 189, '20': 193, '30': 195, '40': 185 }, } }, off: { speed: { 45: { '-10': 301, '0': 317, '10': 323, '20': 330, '30': 336, '40': 339 }, 50: { '-10': 275, '0': 288, '10': 294, '20': 301, '30': 306, '40': 311 }, 55: { '-10': 249, '0': 260, '10': 266, '20': 273, '30': 278, '40': 283 }, 60: { '-10': 225, '0': 236, '10': 241, '20': 248, '30': 251, '40': 258 }, 65: { '-10': 204, '0': 214, '10': 219, '20': 225, '30': 229, '40': 236 }, 70: { '-10': 184, '0': 193, '10': 198, '20': 205, '30': 207, '40': 215 }, } } }, 21: { on: { speed: { 45: { '-10': 223, '0': 255, '10': 287, '20': 289, '30': 288, '40': 260 }, 50: { '-10': 211, '0': 238, '10': 264, '20': 267, '30': 267, '40': 246 }, 55: { '-10': 197, '0': 220, '10': 242, '20': 246, '30': 246, '40': 230 }, 60: { '-10': 183, '0': 203, '10': 221, '20': 225, '30': 227, '40': 212 }, 65: { '-10': 168, '0': 186, '10': 202, '20': 206, '30': 208, '40': 196 }, 70: { '-10': 155, '0': 171, '10': 184, '20': 188, '30': 190, '40': 181 }, } }, off: { speed: { 45: { '-10': 297, '0': 312, '10': 319, '20': 326, '30': 331, '40': 335 }, 50: { '-10': 270, '0': 283, '10': 289, '20': 296, '30': 301, '40': 306 }, 55: { '-10': 244, '0': 256, '10': 261, '20': 268, '30': 272, '40': 278 }, 60: { '-10': 221, '0': 231, '10': 236, '20': 242, '30': 246, '40': 253 }, 65: { '-10': 199, '0': 209, '10': 214, '20': 220, '30': 223, '40': 231 }, 70: { '-10': 180, '0': 188, '10': 193, '20': 200, '30': 202, '40': 210 }, } } } }, '75': { 19: { on: { speed: { 45: { '-10': 271, '0': 309, '10': 347, '20': 350, '30': 347, '40': 312 }, 50: { '-10': 256, '0': 288, '10': 320, '20': 323, '30': 323, '40': 295 }, 55: { '-10': 240, '0': 267, '10': 293, '20': 297, '30': 297, '40': 276 }, 60: { '-10': 222, '0': 246, '10': 268, '20': 272, '30': 273, '40': 257 }, 65: { '-10': 205, '0': 227, '10': 245, '20': 250, '30': 252, '40': 236 }, 70: { '-10': 189, '0': 206, '10': 224, '20': 228, '30': 230, '40': 216 }, } }, off: { speed: { 45: { '-10': 359, '0': 377, '10': 385, '20': 393, '30': 398, '40': 403 }, 50: { '-10': 326, '0': 342, '10': 349, '20': 356, '30': 360, '40': 368 }, 55: { '-10': 296, '0': 309, '10': 316, '20': 323, '30': 326, '40': 335 }, 60: { '-10': 268, '0': 280, '10': 286, '20': 292, '30': 295, '40': 305 }, 65: { '-10': 242, '0': 253, '10': 259, '20': 265, '30': 268, '40': 278 }, 70: { '-10': 219, '0': 229, '10': 234, '20': 241, '30': 244, '40': 253 }, } } }, 21: { on: { speed: { 45: { '-10': 267, '0': 304, '10': 342, '20': 344, '30': 342, '40': 308 }, 50: { '-10': 251, '0': 283, '10': 314, '20': 317, '30': 317, '40': 290 }, 55: { '-10': 235, '0': 262, '10': 287, '20': 291, '30': 291, '40': 271 }, 60: { '-10': 218, '0': 241, '10': 262, '20': 266, '30': 267, '40': 251 }, 65: { '-10': 201, '0': 222, '10': 239, '20': 244, '30': 246, '40': 231 }, 70: { '-10': 184, '0': 203, '10': 218, '20': 223, '30': 224, '40': 211 }, } }, off: { speed: { 45: { '-10': 353, '0': 372, '10': 279, '20': 387, '30': 392, '40': 397 }, 50: { '-10': 320, '0': 336, '10': 343, '20': 350, '30': 354, '40': 361 }, 55: { '-10': 290, '0': 303, '10': 309, '20': 316, '30': 319, '40': 329 }, 60: { '-10': 262, '0': 274, '10': 279, '20': 286, '30': 288, '40': 299 }, 65: { '-10': 237, '0': 247, '10': 253, '20': 259, '30': 262, '40': 272 }, 70: { '-10': 214, '0': 223, '10': 229, '20': 235, '30': 238, '40': 247 }, } } } }, '75D': { 19: { on: { speed: { 45: { '-10': 227, '0': 316, '10': 356, '20': 358, '30': 357, '40': 323 }, 50: { '-10': 262, '0': 296, '10': 328, '20': 332, '30': 332, '40': 305 }, 55: { '-10': 246, '0': 274, '10': 302, '20': 306, '30': 307, '40': 287 }, 60: { '-10': 228, '0': 253, '10': 276, '20': 280, '30': 283, '40': 265 }, 65: { '-10': 211, '0': 233, '10': 253, '20': 257, '30': 260, '40': 246 }, 70: { '-10': 194, '0': 214, '10': 231, '20': 236, '30': 238, '40': 226 }, } }, off: { speed: { 45: { '-10': 368, '0': 387, '10': 395, '20': 404, '30': 410, '40': 415 }, 50: { '-10': 335, '0': 351, '10': 359, '20': 367, '30': 374, '40': 380 }, 55: { '-10': 304, '0': 318, '10': 325, '20': 334, '30': 339, '40': 346 }, 60: { '-10': 275, '0': 288, '10': 294, '20': 303, '30': 307, '40': 316 }, 65: { '-10': 249, '0': 261, '10': 267, '20': 275, '30': 279, '40': 289 }, 70: { '-10': 225, '0': 236, '10': 242, '20': 250, '30': 253, '40': 263 }, } } }, 21: { on: { speed: { 45: { '-10': 273, '0': 311, '10': 351, '20': 354, '30': 352, '40': 318 }, 50: { '-10': 258, '0': 291, '10': 323, '20': 326, '30': 327, '40': 300 }, 55: { '-10': 241, '0': 269, '10': 296, '20': 300, '30': 301, '40': 281 }, 60: { '-10': 223, '0': 248, '10': 270, '20': 275, '30': 277, '40': 259 }, 65: { '-10': 206, '0': 228, '10': 247, '20': 252, '30': 254, '40': 240 }, 70: { '-10': 189, '0': 209, '10': 225, '20': 230, '30': 232, '40': 221 }, } }, off: { speed: { 45: { '-10': 363, '0': 382, '10': 390, '20': 398, '30': 405, '40': 409 }, 50: { '-10': 330, '0': 346, '10': 353, '20': 361, '30': 368, '40': 373 }, 55: { '-10': 299, '0': 312, '10': 319, '20': 327, '30': 333, '40': 340 }, 60: { '-10': 270, '0': 282, '10': 288, '20': 296, '30': 301, '40': 309 }, 65: { '-10': 244, '0': 255, '10': 261, '20': 269, '30': 273, '40': 282 }, 70: { '-10': 219, '0': 230, '10': 236, '20': 244, '30': 247, '40': 257 }, } } } }, '90D': { 19: { on: { speed: { 45: { '-10': 308, '0': 349, '10': 392, '20': 394, '30': 392, '40': 357 }, 50: { '-10': 292, '0': 326, '10': 362, '20': 365, '30': 365, '40': 338 }, 55: { '-10': 273, '0': 303, '10': 332, '20': 336, '30': 337, '40': 317 }, 60: { '-10': 254, '0': 280, '10': 305, '20': 308, '30': 310, '40': 293 }, 65: { '-10': 235, '0': 258, '10': 279, '20': 283, '30': 285, '40': 273 }, 70: { '-10': 216, '0': 238, '10': 256, '20': 260, '30': 263, '40': 253 }, } }, off: { speed: { 45: { '-10': 406, '0': 426, '10': 434, '20': 443, '30': 451, '40': 455 }, 50: { '-10': 370, '0': 386, '10': 394, '20': 403, '30': 412, '40': 416 }, 55: { '-10': 336, '0': 350, '10': 358, '20': 366, '30': 274, '40': 380 }, 60: { '-10': 304, '0': 317, '10': 324, '20': 332, '30': 338, '40': 347 }, 65: { '-10': 276, '0': 288, '10': 295, '20': 302, '30': 308, '40': 317 }, 70: { '-10': 250, '0': 261, '10': 268, '20': 275, '30': 279, '40': 290 }, } } }, 21: { on: { speed: { 45: { '-10': 304, '0': 345, '10': 386, '20': 388, '30': 387, '40': 352 }, 50: { '-10': 287, '0': 321, '10': 356, '20': 359, '30': 360, '40': 332 }, 55: { '-10': 268, '0': 297, '10': 326, '20': 330, '30': 330, '40': 311 }, 60: { '-10': 249, '0': 274, '10': 299, '20': 302, '30': 303, '40': 287 }, 65: { '-10': 230, '0': 253, '10': 273, '20': 277, '30': 279, '40': 267 }, 70: { '-10': 211, '0': 232, '10': 250, '20': 254, '30': 257, '40': 247 }, } }, off: { speed: { 45: { '-10': 401, '0': 420, '10': 428, '20': 437, '30': 446, '40': 449 }, 50: { '-10': 364, '0': 380, '10': 388, '20': 397, '30': 405, '40': 410 }, 55: { '-10': 330, '0': 344, '10': 351, '20': 359, '30': 367, '40': 373 }, 60: { '-10': 298, '0': 311, '10': 318, '20': 325, '30': 331, '40': 340 }, 65: { '-10': 270, '0': 282, '10': 288, '20': 296, '30': 301, '40': 310 }, 70: { '-10': 244, '0': 255, '10': 262, '20': 269, '30': 273, '40': 284 }, } } } }, 'P100D': { 19: { on: { speed: { 45: { '-10': 341, '0': 390, '10': 439, '20': 442, '30': 440, '40': 401 }, 50: { '-10': 323, '0': 365, '10': 405, '20': 409, '30': 410, '40': 380 }, 55: { '-10': 303, '0': 339, '10': 372, '20': 376, '30': 379, '40': 353 }, 60: { '-10': 282, '0': 313, '10': 341, '20': 345, '30': 347, '40': 329 }, 65: { '-10': 261, '0': 289, '10': 312, '20': 317, '30': 318, '40': 306 }, 70: { '-10': 240, '0': 265, '10': 285, '20': 290, '30': 293, '40': 283 }, } }, off: { speed: { 45: { '-10': 447, '0': 474, '10': 485, '20': 496, '30': 505, '40': 509 }, 50: { '-10': 408, '0': 431, '10': 441, '20': 451, '30': 461, '40': 466 }, 55: { '-10': 372, '0': 391, '10': 400, '20': 409, '30': 419, '40': 425 }, 60: { '-10': 337, '0': 354, '10': 362, '20': 371, '30': 377, '40': 388 }, 65: { '-10': 306, '0': 321, '10': 329, '20': 337, '30': 341, '40': 354 }, 70: { '-10': 277, '0': 291, '10': 299, '20': 307, '30': 311, '40': 323 }, } } }, 21: { on: { speed: { 45: { '-10': 322, '0': 369, '10': 414, '20': 417, '30': 416, '40': 379 }, 50: { '-10': 306, '0': 347, '10': 384, '20': 388, '30': 389, '40': 360 }, 55: { '-10': 228, '0': 323, '10': 354, '20': 358, '30': 360, '40': 336 }, 60: { '-10': 269, '0': 299, '10': 325, '20': 329, '30': 331, '40': 313 }, 65: { '-10': 250, '0': 276, '10': 299, '20': 303, '30': 305, '40': 292 }, 70: { '-10': 230, '0': 254, '10': 273, '20': 278, '30': 281, '40': 271 }, } }, off: { speed: { 45: { '-10': 422, '0': 447, '10': 458, '20': 468, '30': 477, '40': 481 }, 50: { '-10': 387, '0': 409, '10': 418, '20': 428, '30': 437, '40': 442 }, 55: { '-10': 353, '0': 372, '10': 380, '20': 389, '30': 398, '40': 404 }, 60: { '-10': 322, '0': 338, '10': 345, '20': 354, '30': 359, '40': 370 }, 65: { '-10': 293, '0': 307, '10': 315, '20': 323, '30': 326, '40': 339 }, 70: { '-10': 265, '0': 279, '10': 286, '20': 294, '30': 298, '40': 310 }, } } } } } }