Exercise 2. Solution
- 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.