PropTypes & Keys

In notebook:
FrontEndMasters React
Created at:
2016-06-14
Updated:
2016-06-22
Tags:
Webpack libraries React JavaScript
What if, he passes 42 instead of ​user.name​ to ​Gravatar​ component? (​return <li><Gravatar email={42} />​)
How to make sure people now what attributes and types to pass to a component, without having to read through all the code to guess it?

You can add ​propTypes​ to a component:
  // **** 2-props/app.js  ****
..

var Gravatar = React.createClass({
    propTypes: {
        email: React.PropTypes.string
    }
})
Now React will give a type warning (in the browser console). This helps other developers to know how to use your component.
The component still works, but in this case, the gravatars don't show up.

Unique element keys

​return <li key={user.id}><Gravatar email={user.email} />..​ 
React uses this when re-renders the component. This helps React to change as little of the DOM as possible [through the diffing algorithm]. 

Custom validation of attribute values

What if we wanted to ensure that the users email address actually contains an "@" symbol?
  // **** 2-props/app.js  ****

// 4. include validateEmail
var validateEmail = require('./validateEmail');
..

// 3. creates emailType checker (copies from original app.js)
var emailType = (props, propName, componentName) => {
  warning(
    //   validateEmail is in another module
    validateEmail(props.email),
    `Invalid email '${props.email}' sent to 'Gravatar'. Check the render method of '${componentName}'.`
  );
};


var Gravatar = React.createClass({
    propTypes: {
        // 1. ++-- changes React.PropTypes.string
        // - email: React.PropTypes.string
        // 2. ++++
        email: emailType
    },
    render () {
        ..
    }
})
propTypes are functions in React. ​React.PropTypes.string​ is a function. ​emailType​ thus is a function as well. The get the parameters ​props​, ​propName​, ​componentName​. 

(For some reason it warns two times when the validation doesn't pass. Doesn't know why.)

Enforcing ​size​ validation

  var Gravatar = React.createClass({
    propTypes: {
        email: emailType
        // 1. ++++ we can also make it _required_
        size: React.PropTypes.number.isRequired
    },
    render () {
        ..
    }
})
Before he updates his code, he says that it would be great to have a default ​size​ set. This can be achieved with ​getDefaultProps()​ life cycle hook
  var Gravatar = React.createClass({
    propTypes: {
        email: emailType
        size: React.PropTypes.number.isRequired
    },
    
    // 1. ++++
    getDefaultProps() {
        return {
            size: 36
        }
    },
    
    render () {
        // 2. ++-- change size
        // -- var size = 36;
        var size = this.props.size;
        var hash = md5(this.props.email);
        var url = `${GRAVATAR_URL}/${hash}?s=${size*2}`;
        return <img src={url} width={size} />
    }
    
})
Great for testing. Put the dependency in ​getDefaultProps​. Like dependency injection. You can pass in a stub for a test.Search for proptypes shows Reusable Components. You see a list of proptypes you can specify. Goes trough the list. There's even a ​shape​ type (color and fontSize).

It's EXTREMELY useful for cooperation with other developers. It serves as a jsdoc for the component.
- What about production? Do you leave this propTypes in?
They're still there. But if it's run with a production flag, React skips them. Then webpack and browserify remove it with the "dead code elimination".

If you're testing and measuring performance, make sure you test the production build, the difference is huge.