Day 1, Segment 4

In notebook:
FrontEndMasters React Intro 2
Created at:
2016-12-23
Updated:
2016-12-23
Tags:
JavaScript Webpack libraries React
Branch v2-9

Turn the dead button into a link

Using the Link module
  // ****   Landing.js  ****

import React from 'react'
// 1. ++++
// import Link for handling links
import { Link } from 'react-router'

const Landing = React.createClass({
  render () {
    return (
      <div className='landing'>
        <h1>svideo</h1>
        <input type='text' placeholder='Search' />
        // 2. ++++
        // use Link tag instead of <a>
        <Link to='/search'>or Browse All</Link>
      </div>
    )
  }
})

export default Landing
use ​<Link>​ instead of ​<a>​ to take advantage of browserrouter

Props

In webpack config add json-loader because we want to load json files
  // ****   webpack.config.js ****

  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      },
      // 1. ++++
      {
        test: /\.json$/,
        loader: 'json-loader'
      },
      {
(questions... 09:00)

Use the JSON data in Search.js
  // ****   Search.js   ****

import React from 'react'
// 1. ++++ add data
import preload from '../public/data.json'

const Search = React.createClass({
  render () {
    return (
      // 2. ++++
      <div className='search'>
      // just print out the data
        <pre><code>{JSON.stringify(preload, null, 4)}</code></pre>
      </div>
    )
  }
})

export default Search

What are the 3 parameters to JSON.stringify?

  1. the data you want to stringify
  2. ​null​ : the replacer function (maybe for passwords ?)
  3. the indentation you want

Transform JSON data structure to markup (iterate/map)

Map a JSON array to markup. React knows how to iterate through arrays.

Explains Array.map (16:50)...
  // ****   Search.js   ****

import React from 'react'
import ShowCard from './ShowCard'
import preload from '../public/data.json'

const Search = React.createClass({
  render () {
    return (
      <div className='search'>
      // 1. ++++
      // map data structure to
      // markup (component)
        {preload.shows.map((show) => {
          return (
            <ShowCard key={show.imdbID} show={show} />
          )
        })}
      </div>
    )
  }
})

export default Search
At this point you will get a warning in the console about unique keys... Will address this later. 

Array.map is not proprietary to React, contrary to ng-repeat. This is really a big difference.

Talks about arrow functions... (replaces the above code)

The Showcard component

   render () {
  // ES6 destructuring....
    const { poster, title, year, description } = this.props.show
    return (
      <div className='show-card'>
        // backticks from ES6
  // (template literals)
        <img src={`/public/img/posters/${poster}`} />
        <div>
          <h3>{title}</h3>
          <h4>({year})</h4>
          <p>{description}</p>
        </div>
      </div>
    )
  }

Whet to extract your code to a new component?

When the code in ​Array.map((elem) => ...​ grows too long is a good sign.

Saves (extracts) the above component to ShowCard.js. 
  // ****  ShowCard.js  ****

import React from 'react'

const ShowCard = React.createClass({
  render () {
    const { poster, title, year, description } = this.props.show
    return (
      <div className='show-card'>
        ...
      </div>
    )
  }
})

export default ShowCard
33:00

Adding unique keys to list items

React needs to identify each element we output from a list structure, so that later it can re-render efficiently (eg. when doing a sort in the UI).
We need create a unique key for each repeating element. 

Above in Search.js it's this ​key={show.imdbID}​:
  {preload.shows.map((show) => {
    return (
      <ShowCard key={show.imdbID} show={show} />
    )
  })}
The imdbID is surely unique, so a good key to use. 

You could also do:
  {preload.shows.map((show) => <ShowCard key={show.imdbID} show={show} />
)}
But Brian argues that it's a bit too dense and hard to read and not ideal for maintainability.

Proptypes

You declare what variables your component expects from its parent.
  // **** ShowCard.js   ****

import React from 'react'
// 1. ++++
const { string } = React.PropTypes

const ShowCard = React.createClass({
  // 2. ++++
  propTypes: {
    poster: string,
    title: string,
    year: string,
    description: string
  },
  render () {
    const { poster, title, year, description } = this.props
    return (
      <div className='show-card'>
        ...
      </div>
    )
  }
})

export default ShowCard

The reason for proptypes

Proptypes are not required by React. They serve as documentation so that you know what to pass to your component when you want to include it. And also for some weak type checking, debugging. 
Make a proptype required
We can even make a proptype required : title: string.isRequired,
What about other static type checking, like Flow?
Flow or Typescript is probably better, but he didn't want to use them for the workshop. They are more powerful than proptypes.

Proptypes are meant for development and not used, or checked in production. You can remove them in your build if you want.