1.10 TeslaStats Component
Now we are going to build the TeslaStats
component. Create the src/components/TeslaStats
directory, create a TeslaStats.js
file in it, and enter the following code:
import React from 'react';import PropTypes from 'react';import './TeslaStats.css';const TeslaStats = (props) => {const listItems = props.carstats.map((stat) => (<li key={stat.model}><div className={'tesla-stats-icon tesla-stats-icon--${stat.model.toLowerCase()}'}></div><p>{stat.miles}</p></li>));return (<div className="tesla-stats"><ul>{listItems}</ul></div>)};TeslaStats.propTypes = {carstats: PropTypes.array}export default TeslaStats;
TeslaStats
is also a presentational component
that receives state, and it takes a list of arrays containing model values by props
and renders them.
First, let’s consider how to transform a list in JavaScript. The following code uses the map()
function to take a numbers
array and return a double value.
This code prints [2, 4, 6, 8, 10]
to the console.
const numbers = [1, 2, 3, 4, 5];const doubled = numbers.map((number) => number * 2);console.log(doubled);
Converting an array to a list in React is almost identical. Here we use the JavaScript map
function to iterate through the props.carstats
array.
For each iteration, it returns a <li>
element containing the model
and a <li>
element surrounding the <p>
tag containing miles
.
Finally, it returns the listItems
array in the <ul>
element.
1.10.1 TeslaStats Component Style
Next, create a TeslaStats.css
file in the src/components/TeslaStats
directory and type the following style. Since the code is long and omitted here, let’s check the source code
....tesla-stats {margin: -70px 0 30px;}.tesla-stats ul {text-align: center;}...
The task that this component performs is to iterate through the props.carstats
array and bind a particular class to an element based on stat.model
. You can then replace the background image to display the Tesla model.
1.10.2 Import TeslaStats component in TeslaBattery Container
Then add following import
to use the TeslaStats
component in TeslaBattery.js
.
...import TeslaStats from '../components/TeslaStats/TeslaStats';...render() {const { config, carstats } = this.state;return (<form className="tesla-battery"><h1>Range Per Charge</h1><TeslaCar wheelsize={config.wheels}/><TeslaStats carstats={carstats}/><TeslaNotice /></form>)}...
We need to pass the carstats
array to props
, so let’s set the value using BatteryService
we’ve already implemented.
1.10.3 CalculateStats and setState
Add import getModelData
first.
After the component is mounted via componentDidMount()
, it calls the statsUpdate()
function. When calculateStats()
function that receives carModels
and the current state value as the input is executed, the object with the matching model
and miles
values is returned, and the return value is passed through the setState()
and then state object is updated.
...import { getModelData } from '../services/BatteryService';...calculateStats = (models, value) => {const dataModels = getModelData();return models.map(model => {// ES6 Object destructuring Syntax,// takes out required values and create references to themconst { 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();}...
One caveat is that explicit binding in the TeslaBattery
constructor function is required to access this
in the class.
...this.calculateStats = this.calculateStats.bind(this);this.statsUpdate = this.statsUpdate.bind(this);...
1.10.4 Add Additional Style
Additional styling is required for a nice layout here.
First open the src/index.css
file and delete all existing code and add the following:
@font-face {font-family: 'RobotoNormal';src: url('./assets/fonts/Roboto-Regular-webfont.eot');src: url('./assets/fonts/Roboto-Regular-webfont.eot?#iefix') format('embedded-opentype'),url('./assets/fonts/Roboto-Regular-webfont.woff') format('woff'),url('./assets/fonts/Roboto-Regular-webfont.ttf') format('truetype'),url('./assets/fonts/Roboto-Regular-webfont.svg#RobotoRegular') format('svg');font-weight: normal;font-style: normal;}*, *:before, *:after {box-sizing: border-box;margin: 0;padding: 0;font: 300 14px/1.4 'Helvetica Neue', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;}.cf:before,.cf:after {content: '';display: table;}.cf:after {clear: both;}.cf {*zoom: 1;}
Next, open the src/App.css
file and delete all existing code and add the following:
.wrapper {margin: 100px 0 150px;}
The work result screen so far is as follows.
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 }, } } } } } }