Exercise 2. Solution

In notebook:
FrontEndMasters React
Created at:
2016-06-14
Updated:
2016-06-14
Tags:
libraries React JavaScript
- Is Typescript useful in the light of propType?
- If you bring in Flow, Typescript is not as interesting. You can't use JSX with it. He doesn't use Typescript. 

- Does Angular have an equivalent of propType?
- Directives can be defined on just a prop. It's not declarative. 

First task, don't use global USERS

  ..

var GRAVATAR_URL = "http://gravatar.com/avatar";

var USERS = [..];

var emailType = (props, propName, componentName) => {
  warning(
    validateEmail(props.email),
    `Invalid email '${props.email}' sent to 'Gravatar'. Check the render method of '${componentName}'.`
  );
};

var Gravatar = React.createClass({
    propTypes: {
        email: emailType
    },
  render () {
    var size = 36;
    var hash = md5(this.props.email);
    var url = `${GRAVATAR_URL}/${hash}?s=${size*2}`;
    return <img src={url} width={size} />
  }
});

var App = React.createClass({
  render () {
    //   2. ++++ change USERS
    // - var users = USERS.map((user) => {
    // ++++
    var users = this.props.users.map((user) => {
        return <li><Gravatar email={user.email}/> {user.name}</li>
    });
    return (
      <div>
        <h1>Users</h1>
        <ul>{users}</ul>
      </div>
    );
  }
});

// 1. ++++ add users prop
React.render(<App users={USERS} />, document.body);
This is great because it's more testable. For example: ​React.render(<App users={[]}, document.body);​ 

Validate Gravatar's size property 

  ..

var GRAVATAR_URL = "http://gravatar.com/avatar";

var USERS = [..];

var emailType = (props, propName, componentName) => {
  warning(
    validateEmail(props.email),
    `Invalid email '${props.email}' sent to 'Gravatar'. Check the render method of '${componentName}'.`
  );
};

// 2. ++++ Creates sizeType check
var sizeType = (props, propName, componentName) => {
  warning(
    !isNaN(parseInt(props[propName])),
    `Hey I can't make that thing a number!`
  );
};

var Gravatar = React.createClass({
    propTypes: {
        email: emailType,
        // 1. ++++ Adds Size check
        size: sizeType
    },
  render () {
    var size = 36;
    var hash = md5(this.props.email);
    var url = `${GRAVATAR_URL}/${hash}?s=${size*2}`;
    return <img src={url} width={size} />
  }
});

var App = React.createClass({
  render () {
    var users = this.props.users.map((user) => {
        return <li><Gravatar email={user.email}/> {user.name}</li>
    });
    return (
      <div>
        <h1>Users</h1>
        <ul>{users}</ul>
      </div>
    );
  }
});

React.render(<App users={USERS} />, document.body);

Generalise email type checking

  ..

var GRAVATAR_URL = "http://gravatar.com/avatar";

var USERS = [..];

var emailType = (props, propName, componentName) => {
  warning(
    //   1. +++ change props.email (generic)
    // ---- validateEmail(props.email),
    validateEmail(props[propName]),
    `Invalid email '${props[propName]}' sent to 'Gravatar'. Check the render method of '${componentName}'.`
  );
};

var sizeType = (props, propName, componentName) => {
  warning(
    !isNaN(parseInt(props[propName])),
    `Hey I can't make that thing a number!`
  );
};

var Gravatar = React.createClass({
    propTypes: {
        // 2. ++-- change this (not necessary but to demonstrate)
        // ----email: emailType,
        loginID: emailType,
        size: sizeType
    },
    
    getDefaultProps () {
        return {
            size: 16
        };
    },
    
  render () {
    //   3. ++-- updates values here too
    // ---- var size = 36;
    var {loginID, size} = this.props;
    var hash = md5(this.props.email);
    var url = `${GRAVATAR_URL}/${hash}?s=${size*2}`;
    return <img src={url} width={size} />
  }
});

var App = React.createClass({
  render () {
    var users = this.props.users.map((user) => {
        return <li><Gravatar email={user.email}/> {user.name}</li>
    });
    return (
      <div>
        <h1>Users</h1>
        <ul>{users}</ul>
      </div>
    );
  }
});

React.render(<App users={USERS} />, document.body);

How many times does the "getDefaultProps" get called?

Only once, the first time the first element gets rendered. So you cannot create dynamic values here.