SlideShare uma empresa Scribd logo
1 de 169
Baixar para ler offline
ReactJS
for Programmers
by Dr. David Rodenas
Origin
2014
FB about Web
3
https://youtu.be/nYkdrAPrdcw?t=10m20s
FB about MVC
4
“MVC works pretty well
for small applications…
but it doesn’t make room
for new features.”
“Flux is a single direction data flow,
that avoids all the arrows
going on all directions
what makes really
hard to understand the system.”
FB about Chat
5
“Let’s see a real good example: FB chat”
“How we get to the point, so we were annoying our
users so much the just they wanted us to fix chat?”
“The problems here were:
• The code has no structure
• It was very imperative, that makes it fragile
• It loose a lot of the original intend behind it, its hard to tell what it tries [to do]
• Add more features only gets this code larger
• We had our most annoying chat bug happen over and over
• We were always fixing some pretty good edge case, the whole system was fragile
• …
• This code becomes more fragile with the time.
• No member of the team wanted to touch it, they wanted to jump to any other bug.”
FB about Rendering
6
“Imperative Rendering”
“If renders all each time
the screen flickers”
“We wanted always render all, no matter what”
“Here is where React comes in.”
FB & Virtual DOM
7
ReactJS
Prerequisite
9
Install React Developer Tools
Basics
Hello World
<!-- hello-world.html -->
<div id="root"></div>
// hello-world.js
const virtualDom = React.createElement(
'h1', null, 'Hello, world!'
);
ReactDOM.render(
virtualDom,
document.getElementById('root')
);
11
Hello World
<!-- hello-world.html -->
<div id="root"></div>
// hello-world.jsx
const virtualDom = <h1>Hello, world!</h1>;
ReactDOM.render(
virtualDom,
document.getElementById('root')
);
12
Hello World
<!-- hello-world.html -->
<div id="root"></div>
// hello-world.jsx
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
13
https://facebook.github.io/react/docs/hello-world.html
Hello World
// This is translated by Babel to...
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
// ...to this
ReactDOM.render(React.createElement(
'h1',
null,
'Hello, world!'
), document.getElementById('root'));
14
https://babeljs.io/repl
• ReactJS only updates what changes
• Although everything is regenerated every time
• Open countdown example at codepen with chrome

http://codepen.io/drpicox/pen/yMKWGN
• Inspect page
• You can see that only the span is updated

(although this crude code changes everything)
Do not fear change
15
JSX
https://facebook.github.io/react/docs/introducing-jsx.html
JSX
// Just sugar syntax
const element = <h1>Hello, world!</h1>;
// It is just one object
const element = React.createElement(
"h1",
null,
"Hello, world!"
);
// one object that you can manipulate as object
17
JSX
// May I?
console.log(<h1>Hello!</h1>);
console.log(<h1>Hello!</h1>.toString());
console.log([<h1>Hello!</h1>]);
console.log({hello: <h1>Hello!</h1>});
console.log((() => <h1>Hello!</h1>)());
const salute = (what) => <h1>{what}!</h1>;
console.log(salute('Hello'));
18
JSX
// Have multiple elements (but one wrapper)
const element = <h1><span>Hello</span>, world!</h1>;
// Generates
const element = React.createElement(
"h1",
null,
React.createElement(
"span",
null,
"Hello"
),
", world!"
);
19
JSX
// It can be multiline (be careful using return)
const element =
<h1>
Hello, world!
</h1>;
20
JSX
// It can be multiline (better)
const element = <h1>
Hello, world!
</h1>;
21
JSX
// It can be multiline (recommended)
const element = (
<h1>
Hello, world!
</h1>
);
22
JSX - Interpolation
// Interpolate any JS expression
const name = 'bob hoskings';
const element = (
<h1>
Hello, {name}!
</h1>
);
// It is just one argument more
const element = React.createElement(
'h1',
null,
'Hello, ',
name,
'!'
);
23
JSX - Interpolation
// Interpolate any JS expression
const user = {name:'bob', lastName:'hoskings'};
const element = (
<h1>
Hello, {user.name + ' ' + user.lastName}!
</h1>
);
// It is still just one argument more
const element = React.createElement(
'h1',
null,
'Hello, ',
user.name + ' ' + user.lastName,
'!'
);
24
JSX - Interpolation
// any expression, including JSX
const element = <h1>Hello, {<span>world</span>}!</h1>
// It is still just one argument more
const element = React.createElement(
"h1",
null,
"Hello, ",
React.createElement(
"span",
null,
"world"
),
"!"
);
25
JSX - Properties
// Add attributes
const element = <div tabIndex="0">...</div>;
// Is transformed into a property object (alias props)
const element = React.createElement(
"div",
{ tabIndex: "0" },
"..."
);
26
JSX - Properties
// Add computed attributes
const element = <img src={user.imageUrl} />;
// Is transformed into a property object (alias props)
const element = React.createElement(
"img",
{ src: user.imageUrl },
);
27
JSX - Properties
// Set variable attributes
const options = {
autoplay: true,
muted: true,
};
const element = <video src="wow.mp4" {...options} />;
// Are merged into attribute
const element = React.createElement(
"video",
{
src: "wow.mp4",
...options
},
);
28
JSX - Properties
// Set variable attributes
const options = {
autoplay: true,
muted: true,
};
const element = <video src="wow.mp4" {...options} />;
// Are merged into attribute
const element = React.createElement(
"video",
{
src: "wow.mp4",
autoplay: true, muted: true
},
);
29
Properties vs Attributes
<!-- html uses attributes -->
<img id="hello" src="hello.jpg">
<!-- javascript uses properties -->
const helloImg = document.getElementById('hello');
console.log(helloImg.src);
30
Properties vs Attributes
<!-- html uses attributes -->
<h1 id="hello" class="big">Hello</h1>
<!-- javascript uses properties -->
const helloH1 = document.getElementById('hello');
console.log(helloH1.className);
31
JSX - Properties
// Because bad IE8 habits: className instead of class
const element = <h1 className="big">Hello</h1>;
// Is rendered as real html attribute:
<h1 class="big">Hello</h1>
32
JSX - Cross-site-scripting
// It is just a string
const title = response.veryMaliciousInputString;
// This is save
const element = <h1>{title}</h1>;
33
JSX - XML
// Is XML-like
const element = (
<div>
Hello <br/> World
</div>
);
// Elements must be terminated
const element = (
<div>
Hello <br> World
</div>
);
34
Rendering Elements
https://facebook.github.io/react/docs/rendering-elements.html
Rendering Elements
// JSX elements are just memory objects
const element = <h1>Hello, world</h1>;
36
Rendering Elements
// Given an html DOM element
<div id="root"></div>
// they can be rendered inside DOM
const domElement = document.getElementById('root');
const reactElement = <h1>Hello, world</h1>;
ReactDOM.render(
reactElement,
/* into */ domElement
);
37
Rendering Elements
// As many times as you want
// react only updates changes
const domElement = document.getElementById('root');
let n = 0;
setInterval(() => {
ReactDOM.render(<h1>{n += 1}</h1>, domElement);
}, 1000);
38
Components and Props
https://facebook.github.io/react/docs/components-and-
props.html
Components
// Can be defined as functions
const HelloWorld = () => {
return <h1>Hello, world</h1>;
};
export default HelloWorld;
40
Components
// Can be defined as functions
const HelloWorld = () => {
return <h1>Hello, world</h1>;
};
export default HelloWorld;
// Can be defined as classes
export default class HelloWorld extends React.Component
{
render() {
return <h1>Hello, world</h1>;
}
}
41
Component and properties
const element = <Welcome name="Dave" />;
42
Component and properties
const element = <Welcome name="Dave" />;
// Remember: it is like write
const element = React.createElement(
Welcome,
{ name: "Dave" }, // are called props
);
43
Component and properties
const element = <Welcome name="Dave" />;
// This is how you define the Component to use props
function Welcome(props) {
return (
<h1>Hello {props.name}!</h1>
);
}
44
Component and properties
const element = <Welcome name="Dave" />;
// This is how you define the Component to use props
class Welcome extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>Hello {this.rops.name}!</h1>
);
}
}
45
Composing Components
function App() {
return (
<div>
<Welcome name="Alice" />
</div>
);
}
46
Composing Components
function App() {
return (
<div>
<Welcome name="Alice" />
<Welcome name="Bob" />
<Welcome name="Dave" />
</div>
);
}
47
Refactoring Components
function Component(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
48
Refactoring Components
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
49
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
Refactoring Components
function Component(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
50
Refactoring Components
function Component(props) {
return (
<div className="Comment">
<div className="UserInfo">
<Avatar user={props.author} />
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
51
Refactoring Components
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
52
Refactoring Components
function Component(props) {
return (
<div className="Comment">
<UserInfo user={props.author} />
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{formatDate(props.date)}
</div>
</div>
);
}
53
Props are Read-Only
// Render must be read-only
function MissbehavingComponent(props) {
return <h1>{props.n += 1}</h1>;
}
54
State and Lifecycle
https://facebook.github.io/react/docs/state-and-lifecycle.html
Function to Class Component
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.time}.</h2>
</div>
);
}
56
Function to Class Component
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.time}.</h2>
</div>
);
}
}
57
Function to Class Component
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.time}.</h2>
</div>
);
}
}
58
Setup State
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {time: Date.now()};
}
render() { ... }
}
59
Setup State
class Clock extends React.Component {
constructor(props) { ... }
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.time}.</h2>
</div>
);
}
}
60
Lifecycle Methods
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() { /* TODO */ }
componentWillUnmount() { /* TODO */ }
render() { ... }
}
61
Lifecycle Methods
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() {
this.timerId = setInterval(
() => this.setState({time: Date.now()}),
1000
);
}
componentWillUnmount() { /* TODO */ }
render() { ... }
}
62
Lifecycle Methods
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() { ... }
componentWillUnmount() {
clearInterval(this.timerId);
}
render() { ... }
}
63
setState Asynchronous
// Wrong!
setState({counter: this.state.counter + 1});
// Correct
setState((prevState, props) => ({
counter: prevState.counter + 1
});
64
States are Merged
constructor() {
this.state = {posts: [], users: []};
}
componentDidMount() {
getPosts((posts) => this.setState({posts}));
getUsers((users) => this.setState({users}));
}
65
State Isolated
function App() {
return (
<div>
<Clock />
<Clock />
<Clock />
</div>
);
}
66
Handling Events
https://facebook.github.io/react/docs/handling-events.html
onEvent={fn}
function ButtonLogHello() {
function handleClick() {
console.log('The button is clicked');
}
return (
<button onClick={handleClick}>
click me
</button>
);
}
68
onEvent={fn}
// It received the event as parameter
function ALogHello() {
function handleClick(ev) {
ev.preventDefault();
console.log('The link is clicked');
}
return (
<a href="#" onClick={handleClick}>
click me
</a>
);
}
69
onEvent={fn}
// It can inline functions (are expressions)
function DivLogHello() {
return (
<button onClick={() => console.log('oh')}>
click me
</button>
);
}
70
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
}
...
71
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
}
handleClick() { ... }
...
72
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
// This binding is necessary by `this`
this.handleClick = this.handleClick.bind(this);
}
handleClick() { ... }
...
73
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
// Fat arrow function preserves `this`
this.handleClick = () => { ... };
}
...
74
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
}
// Stage 2 alternative (recommended official)
handleClick = () => { ... }
...
75
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
}
handleClick = () => { … }
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'on' : 'off'}
</button>
);
}
}
76
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
}
handleClick = () => {
// Warning, wrong implementation
this.setState({ isToggleOn: !this.state.isToggleOn });
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'on' : 'off'}
</button>
);
}
}
77
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = { isToggleOn: true };
}
handleClick = () => {
this.setState((prevState) => ({
isToggleOn: !prevState.isToggleOn,
});
}
render() {
return (
<button onClick={this.handleClick}>
{this.state.isToggleOn ? 'on' : 'off'}
</button>
);
}
}
78
Conditional Rendering
https://facebook.github.io/react/docs/conditional-
rendering.html
Conditional Rendering
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
80
By return
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
// Try changing to isLoggedIn={true}:
<Greeting isLoggedIn={false} />,
document.getElementById('root')
);
81
By variable
render() {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} /
>;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
82
By && expression
function Mailbox(props) {
const unreadMessages = props.unreadMessages;
return (
<div>
<h1>Hello!</h1>
{unreadMessages.length > 0 &&
<h2>
You have {unreadMessages.length} unread
messages.
</h2>
}
</div>
);
}
83
By ?: expression
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton
onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
84
Prevent Render
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
Warning!
</div>
);
}
85
Lists and Keys
https://facebook.github.io/react/docs/lists-and-keys.html
Remember...
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((n) => n * 2);
console.log(doubled);
// [2, 4, 6, 8, 10]
87
Render Multiple
// Render a reactElements array
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
<li>{number}</li>
);
ReactDOM.render(
<ul>{listItems}</ul>,
document.getElementById('root')
);
88
Render Multiple
// Refactor into component
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li>{number}</li>
);
return (
<ul>{listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
89
Key
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
90
Key - index
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);
91
Key - Refactor Component
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
92
Key - Refactor Component
function ListItem(props) {
return (
// Wrong! should not be here
<li key="props.number.toString()">
{props.number}
</li>
);
}
93
Key - Refactor Component
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// Correct: key must remain with map
<ListItem key={number.toString()}
number={number} />
{number}
);
return (
<ul>{listItems}</ul>
);
}
94
Key - Uniqueness
// Cannot repeat keys in the same list, but...
function DoubleList(props) {
return (
<div>
<NumberList numbers={props.numbers} />
<NumberList numbers={props.numbers} />
<NumberList numbers={props.numbers} />
</div>
);
}
95
.map inside JSX
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
96
Forms
https://facebook.github.io/react/docs/forms.html
Controlled Components
class NameForm extends React.Component {
constructor() { ... }
handleChange = (event) => {
this.setState({value: event.target.value});
}
handleSubmit = (event) => { ... }
render() {
return (
<form onSubmit={this.handleSubmit}>
<input type="text"
value={this.state.value}
onChange={this.handleChange} />
</form>
);
}
}
98
Controlled Components
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
}
handleChange = (event) => { ... }
handleSubmit = (event) => { ... }
render() { ... }
}
99
Controlled Components
class NameForm extends React.Component {
constructor() { ... }
handleChange = (event) => {
this.setState({
value: event.target.value.toLowerCase()
});
}
handleSubmit = (event) => { ... }
render() { ... }
}
100
Textarea
<textarea
value={this.state.value}
onChange={this.handleChange}
/>
101
Select
<select
value={this.state.value}
onChange={this.handleChange}>
<option value="grapefruit">Grapefruit</option>
<option value="lime">Lime</option>
<option value="coconut">Coconut</option>
<option value="mango">Mango</option>
</select>
102
Multiple Inputs
<input
name="isGoing" type="checkbox"
checked={this.state.isGoing}
onChange={this.handleInputChange} />
<input
name="numberOfGuests" type="number"
value={this.state.numberOfGuests}
onChange={this.handleInputChange} />
103
Multiple Inputs
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ?
target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
104
Synchronized States
https://facebook.github.io/react/docs/lifting-state-up.html
Synchronizing - Consumer
// We want an <input> to generate new values for
function BoilingVerdict(props) {
if (props.celsius >= 100) {
return <p>The water would boil.</p>;
}
return <p>The water would not boil.</p>;
}
106
Synchronizing - Coordinator
class Calculator extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: e.target.value});
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</fieldset>
);
}
}
107
Synchronizing - Producer
class Calculator extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: e.target.value});
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</fieldset>
);
}
}
108
Synchronizing - Producer
class TemperatureInputCelsius extends React.Component {
constructor(props) { ... }
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
109
Synchronizing - Producer
class TemperatureInputCelsius extends React.Component {
constructor(props) { ... }
handleChange
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
110
Synchronizing - Producer
class TemperatureInputCelsius extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: e.target.value});
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
111
Synchronizing - Producer
class TemperatureInputCelsius extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: e.target.value});
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
112
Synchronizing - Coordinator
class Calculator extends React.Component {
constructor(props) { ... }
handleChange = (...?) =>
this.setState({temperature: ...?});
render() {
const temperature = this.state.temperature;
return (
<TemperatureInputCelsius ...? ...? />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</fieldset>
);
}
}
113
Synchronizing - Coordinator
class Calculator extends React.Component {
constructor(props) { ... }
handleChange = (temperature) =>
this.setState({temperature: temperature});
render() {
const temperature = this.state.temperature;
return (
<TemperatureInputCelsius
temperature={temperature}
onTemperatureChange={this.handleChange} />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</fieldset>
);
}
}
114
Synchronizing - Producer
class TemperatureInputCelsius extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: e.target.value});
render() {
const temperature = this.state.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
115
Synchronizing - Producer
class TemperatureInputCelsius extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.props.onTemperatureChange(e.target.value);
render() {
const temperature = this.props.temperature;
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
116
Synchronizing - Coordinator
117
Calculator
this: { handleChange }
state: { temperature }
props: { temperature }
BoilingVeredict
props: { temperature,
onTemperatureChange }
TemperatureInputCelsius
Synchronizing - Multiple Producer
Calculator
TemperatureInput => Celsius and Fahrenheit
118
Synchronizing - Producer
class TemperatureInput extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: e.target.value});
render() {
const temperature = this.state.temperature;
const scaleName = scaleNames[this.props.scale];
return (
<fieldset>
<legend>Enter temperature in {scaleName}:</
legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
119
Synchronizing - Producer
class Calculator extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: ...?});
render() {
const temperature = this.state.temperature;
return (
<div>
<TemperatureInput scale="c" ...? ...? />
<TemperatureInput scale="f" ...? ...? />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</div>
);
}
}
120
Synchronizing - Producer
class TemperatureInput extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.props.onTemperatureChange(e.target.value);
render() {
const temperature = this.props.temperature;
const scaleName = scaleNames[this.props.scale];
return (
<fieldset>
<legend>Enter temperature in {scaleName}:</
legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
121
Synchronizing - Coordinator
class Calculator extends React.Component {
constructor(props) { ... }
handleChange = (e) =>
this.setState({temperature: ...?});
render() {
const temperature = this.state.temperature;
return (
<div>
<TemperatureInput scale="c" ...? ...? />
<TemperatureInput scale="f" ...? ...? />
<BoilingVerdict
celsius={parseFloat(temperature)} />
</div>
);
}
}
122
Coordinator - Inputs
class Calculator extends React.Component {
...
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = convertIf(scale === 'f', temperature,
toCelsius);
const fahrenheit = convertIf(scale === 'c', temperature,
toFahrenheit);
return (
<div>
<TemperatureInput scale="c" temperature={celsius} ...? />
<TemperatureInput scale="f" temperature={fahrenheit} ...? />
<BoilingVerdict
celsius={parseFloat(celsius)} />
</div>
);
}
}
123
Coordinator Outputs
class Calculator extends React.Component {
...
handleCelsiusChange = (temperature) =>
this.setState({scale: 'c', temperature});
handleFahrenheitChange = (temperature) =>
this.setState({scale: 'f', temperature});
render() {
const scale = this.state.scale;
const temperature = this.state.temperature;
const celsius = convertIf(scale === 'f', temperature,
toCelsius);
...
<TemperatureInput scale="c" temperature={celsius}
onTemperatureChange={this.handleCelsiusChange} />
<TemperatureInput scale="f" temperature={fahrenheit}
onTemperatureChange={this.handleFahrenheitChange} />
...
}
}
124
Coordinator Outputs
function convertIf(test, temperature, convert) {
if (test) {
return tryConvert(temperature, convert);
}
return temperature;
}
125
Exercise
126
https://codepen.io/drpicox/pen/ryrypJ
Exercise React Temperature
Component Composition
https://facebook.github.io/react/docs/composition-vs-
inheritance.html
Java 1.0
128
http://web.mit.edu/java_v1.0.2/www/apibook/javag2.htm
An application should override the action method (II-
§1.10.1) of the button or of one of its containing windows
in order to cause some action to occur.
Button
+ action(...)
MyButton
+ action(...)
Java 1.1
129
In 1.1, we aimed at solving some major AWT (Abstract
Window Toolkit) deficiencies, with a strong focus on quality
and performance. The AWT enhancements include [...], a
delegation-based event model, [...].
Button
+ actionActionListener(...)
https://www.cs.princeton.edu/courses/archive/fall97/cs461/
jdkdocs/guide/awt/index.html
<i> ActionListener
+ actionPerformed(...) = 0
MyActionListener
+ actionPerformed(...)
*
Java 1.2
130
When an Action object is added to such a container, the container:
Creates a component that is appropriate for that container (a toolbar
creates a button component, for example), Gets the appropriate
property(s) from the Action object to customize the component (for
example, the icon image and flyover text)....
<i> Action
+ actionPerformed(...) = 0
+ isEnabled(): bool
+ setEnabled(b)
+ getValue(key): Object
+ putValue(key, value)
+ addPropertyChangeListener(...)
+ removePropertyChangeListener(...)
http://www.kbs.twi.tudelft.nl/Documentation/Programming/
Java/jdk1.2/api/javax/swing/Action.html
Children Composition
131
Card
Contents
Children Composition
<Card>
<h1>Welcome</h1>
<p>
Find here a complete list
of all the things that you
love.
</p>
</Card>
132
Children Composition
function Card(props) {
return (
<div className="card">
{props.children}
</div>
);
}
133
Many Children Composition
134
SplitPane
Left Right
Many Children Composition
<div class="SplitPane">
<div class="SplitPane-left">
<Contacts />
</div>
<div class="SplitPane-right">
<Chat />
</div>
</div>
135
Many Children Composition
function SplitPane(props) {
return (
<div className="SplitPane">
<div className="SplitPane-left">
{props.left}
</div>
<div className="SplitPane-right">
{props.right}
</div>
</div>
);
}
136
Many Children Composition
function App() {
return (
<SplitPane
left={ <Contacts /> }
right={ <Chat /> }
/>
);
}
137
Specialization
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
138
Specialization
function WelcomeDialog(props) {
return (
<Dialog
title="Welcome"
message="Thanks for visiting!" />
);
}
139
Specialization
function WelcomeDialog(props) {
return (
<Dialog
title="Welcome"
message={
<div>
<h1>Thanks!</h1>
for visiting!
</div>
} />
);
}
140
High Order Components
https://facebook.github.io/react/docs/higher-order-
components.html
Like high order functions
const safeConvert = (convert) => {
return (temperature) => {
const input = parseFloat(temperature);
if (Number.isNaN(input)) {
return '';
}
const output = convert(input);
const rounded = Math.round(output * 100) / 100;
return rounded.toString();
}
}
142
Like high order functions
const safeConvert = (convert) => {
return (temperature) => {
...
}
}
const safeKelvinToCelsius =
safeConvert(kelvinToCelsius);
const celsius = safeKelvinToCelsius(kelvin);
143
Specific Component
class TemperatureInputCelsius extends React.Component {
handleChange = (e) => this.props.onTemperatureChange(
safeCelsiusToKelvin(e.target.value);
);
render() {
const temperature = this.props.temperature;
const celsius = safeKelvinToCelsius(temperature);
return (
<fieldset>
<legend>Enter temperature in Celsius:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
144
Specific Component
class TemperatureInputFahrenheit extends React.Component {
handleChange = (e) => this.props.onTemperatureChange(
safeFahrenheitToKelvin(e.target.value);
);
render() {
const temperature = this.props.temperature;
const celsius = safeKelvinToFahrenheit(temperature);
return (
<fieldset>
<legend>Enter temperature in Fahrenheit:</legend>
<input value={temperature}
onChange={this.handleChange} />
</fieldset>
);
}
}
145
Generic Component
class TemperatureInput? extends React.Component {
handleChange = (e) => this.props.onTemperatureChange(
toKelvin(e.target.value);
);
render() {
const temperature = this.props.temperature;
const local = toLocal(temperature);
return (
<fieldset>
<legend>Enter temperature in {scaleName}:</
legend>
<input value={local}
onChange={this.handleChange} />
</fieldset>
);
}
}
146
Generic Component
function makeTemperatureInput(toKelvin, toLocal, scaleName) {
return class extends React.Component {
handleChange = (e) => this.props.onTemperatureChange(
toKelvin(e.target.value);
);
render() {
const temperature = this.props.temperature;
const local = toLocal(temperature);
return (
<fieldset>
<legend>Enter temperature in {scaleName}:</legend>
<input value={local}
onChange={this.handleChange} />
</fieldset>
);
}
}
}
147
Using Generic Component
const TemperatureInputCelsius = makeTemperatureInput(
safeCelsiusToKelvin,
safeKelvinToCelsius,
'Celsius'
);
const TemperatureInputFahrenheit = makeTemperatureInput(
safeFahrenheitToKelvin,
safeKelvinToFahrenheit,
'Fahrenheit'
);
const TemperatureInputKelvin = makeTemperatureInput(
identity,
identity,
'Kelvin'
);
148
Using Generic Component
const TemperatureInputCelsius = makeTemperatureInput(
safeConvert(celsiusToKelvin),
safeConvert(kelvinToCelsius),
'Celsius'
);
const TemperatureInputFahrenheit = makeTemperatureInput(
safeConvert(fahrenheitToKelvin),
safeConvert(kelvinToFahrenheit),
'Fahrenheit'
);
const TemperatureInputKelvin = makeTemperatureInput(
(x) => x,
(x) => x,
'Kelvin'
);
149
High Order Component
class Thermostat extends React.Component {
constructor(props) { ... }
handleChangeMax = (e) => ...
handleChangeMin = (e) => ...
render() {
return (
<div>
Max <TemperatureInput
temperature={this.state.max}
onTemperatureChange={this.handleChangeMax} />
Min <TemperatureInput
temperature={this.state.min}
onTemperatureChange={this.handleChangeMin} />
</div>
);
}
}
150
High Order Component
function makeThermostat(TemperatureInput) {
return class extends React.Component {
constructor(props) { ... }
handleChangeMax = (e) => ...
handleChangeMin = (e) => ...
render() {
return (
<div>
Max <TemperatureInput temperature={this.state.max}
onTemperatureChange={this.handleChangeMax} />
Min <TemperatureInput temperature={this.state.max}
onTemperatureChange={this.handleChangeMax} />
</div>
);
}
}
}
151
High Order Component
function makeThermostat(TemperatureInput) {
return class extends React.Component {
...
}
}
const ThermostatCelsius =
makeThermostat(TemperatureInputCelsius);
const ThermostatFahrenheit =
makeThermostat(TemperatureInputFahrenheit);
const ThermostatKelvin =
makeThermostat(TemperatureInputKelvin);
152
Debug: displayName
function makeTemperatureInput(
toKelvin, toFahrenheit, scaleName
) {
class TemperatureInput extends React.Component {
...
}
TemperatureInput.displayName =
`TemperatureInput(${scaleName})`;
return TemperatureInput;
}
153
Debug: displayName
function makeThermostat(TemperatureInput) {
class Thermostat extends React.Component {
...
}
Thermostat.displayName =
`Thermostat(${getDisplayName(TemperatureInput)})`;
return Thermostat;
}
154
Warning!
// DON'T use HOCs in render functions!
const App = () => {
const TemperatureInputAbc =
makeTemperatureInput(a, b, c);
return <TemperatureInputAbc />;
}
class App extends React.Component {
render() {
const TemperatureInputAbc =
makeTemperatureInput(a, b, c);
return <TemperatureInputAbc />;
}
}
155
More in docs
• Use HOCs For Cross-Cutting Concerns
• Don't Mutate the Original Component. 

Use Composition.
• Convention: Pass Unrelated Props Through to the Wrapped
Component
• Convention: Maximizing Composability
• Convention: Wrap the Display Name for Easy Debugging
• Caveats
156
Containers
https://medium.com/@dan_abramov/smart-and-dumb-
components-7ca2f9a7c7d0
Convention
• Types of components
• Routers
• Containers
• Presentational
158
Routes
• Routers
• Decides which component to render
• Create components dynamically
• Usually provided by library
159
Containers
• Knows how to load or mutate data
• Observe Stores
• Dispatch Actions
• Other system interactions
• Always stateful (class notation)
• Renders nothing
• Delegates render to a Presentational Component
• Configures its props
160
Presentational
• Knows how to render things
• Data and callbacks only via props
• does not interact with the application
• Usually functional (not need state)
• Also called Components
161
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() {
this.timerId = setInterval(
() => this.setState({time: Date.now()}),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerId);
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.time}.</h2>
</div>
);
}
}
162
Presentational
Container
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() {
this.timerId = setInterval(
() => this.setState({time: Date.now()}),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerId);
}
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.time}.</h2>
</div>
);
}
}
163
Presentational
Container
Presentational Refactor
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.time}.</h2>
</div>
);
}
164
Container Refactor
class IntervalClock extends React.Component {
constructor(props) { ... }
componentDidMount() {
this.timerId = setInterval(
() => this.setState({time: Date.now()}),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerId);
}
render() {
return <Clock time={this.state.time} />;
}
}
165
Container Refactor
function makeIntervalClock(Clock) {
return class extends React.Component {
constructor(props) { ... }
componentDidMount() {
this.timerId = setInterval(
() => this.setState({time: Date.now()}),
1000
);
}
componentWillUnmount() {
clearInterval(this.timerId);
}
render() {
return <Clock time={this.state.time} />;
}
};
}
166
PropTypes
https://facebook.github.io/react/docs/typechecking-with-
proptypes.html
PropTypes
import PropTypes from 'prop-types';
export default function Welcome(props) {
return (
<h1>Hello, {props.name}</h1>
);
}
Welcome.propTypes = {
name: PropTypes.string
};
168
https://facebook.github.io/react/docs/typechecking-with-proptypes.html
PropTypes
import PropTypes from 'prop-types';
export default class Welcome extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Welcome.propTypes = {
name: PropTypes.string.isRequired
};
169
https://facebook.github.io/react/docs/typechecking-with-proptypes.html

Mais conteúdo relacionado

Mais procurados

Pyconie 2012
Pyconie 2012Pyconie 2012
Pyconie 2012
Yaqi Zhao
 
Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011
Anton Arhipov
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
Tomek Kaczanowski
 

Mais procurados (20)

Inside PyMongo - MongoNYC
Inside PyMongo - MongoNYCInside PyMongo - MongoNYC
Inside PyMongo - MongoNYC
 
Pyconie 2012
Pyconie 2012Pyconie 2012
Pyconie 2012
 
Spock Framework
Spock FrameworkSpock Framework
Spock Framework
 
Building unit tests correctly
Building unit tests correctlyBuilding unit tests correctly
Building unit tests correctly
 
Unit testing patterns for concurrent code
Unit testing patterns for concurrent codeUnit testing patterns for concurrent code
Unit testing patterns for concurrent code
 
關於測試,我說的其實是......
關於測試,我說的其實是......關於測試,我說的其實是......
關於測試,我說的其實是......
 
Spock Testing Framework - The Next Generation
Spock Testing Framework - The Next GenerationSpock Testing Framework - The Next Generation
Spock Testing Framework - The Next Generation
 
Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011
 
Celery
CeleryCelery
Celery
 
33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests33rd Degree 2013, Bad Tests, Good Tests
33rd Degree 2013, Bad Tests, Good Tests
 
GeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassleGeeCON 2017 - TestContainers. Integration testing without the hassle
GeeCON 2017 - TestContainers. Integration testing without the hassle
 
TDD Training
TDD TrainingTDD Training
TDD Training
 
Agile Android
Agile AndroidAgile Android
Agile Android
 
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, howTomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
Tomasz Polanski - Automated mobile testing 2016 - Testing: why, when, how
 
Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013Workshop quality assurance for php projects - ZendCon 2013
Workshop quality assurance for php projects - ZendCon 2013
 
UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013UA testing with Selenium and PHPUnit - PFCongres 2013
UA testing with Selenium and PHPUnit - PFCongres 2013
 
Agile Swift
Agile SwiftAgile Swift
Agile Swift
 
Maintainable JavaScript 2011
Maintainable JavaScript 2011Maintainable JavaScript 2011
Maintainable JavaScript 2011
 
Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016Unit testing without Robolectric, Droidcon Berlin 2016
Unit testing without Robolectric, Droidcon Berlin 2016
 
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
15 tips to improve your unit tests (Droidcon Berlin 2016 Barcamp)
 

Semelhante a ReactJS for Programmers

react-slides.pdf gives information about react library
react-slides.pdf gives information about react libraryreact-slides.pdf gives information about react library
react-slides.pdf gives information about react library
janet736113
 
Jquery dojo slides
Jquery dojo slidesJquery dojo slides
Jquery dojo slides
helenmga
 

Semelhante a ReactJS for Programmers (20)

Basic Tutorial of React for Programmers
Basic Tutorial of React for ProgrammersBasic Tutorial of React for Programmers
Basic Tutorial of React for Programmers
 
Getting Started with React v16
Getting Started with React v16Getting Started with React v16
Getting Started with React v16
 
Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]Full Stack React Workshop [CSSC x GDSC]
Full Stack React Workshop [CSSC x GDSC]
 
React js
React jsReact js
React js
 
React - Start learning today
React - Start learning today React - Start learning today
React - Start learning today
 
React outbox
React outboxReact outbox
React outbox
 
ReactJS.ppt
ReactJS.pptReactJS.ppt
ReactJS.ppt
 
Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017Building Universal Web Apps with React ForwardJS 2017
Building Universal Web Apps with React ForwardJS 2017
 
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
Universal JS Web Applications with React - Web Summer Camp 2017, Rovinj (Work...
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
 
Reactive Type-safe WebComponents
Reactive Type-safe WebComponentsReactive Type-safe WebComponents
Reactive Type-safe WebComponents
 
react-slides.pptx
react-slides.pptxreact-slides.pptx
react-slides.pptx
 
React Native for multi-platform mobile applications
React Native for multi-platform mobile applicationsReact Native for multi-platform mobile applications
React Native for multi-platform mobile applications
 
Reactive Type safe Webcomponents with skateJS
Reactive Type safe Webcomponents with skateJSReactive Type safe Webcomponents with skateJS
Reactive Type safe Webcomponents with skateJS
 
react-slides.pdf
react-slides.pdfreact-slides.pdf
react-slides.pdf
 
react-slides.pdf gives information about react library
react-slides.pdf gives information about react libraryreact-slides.pdf gives information about react library
react-slides.pdf gives information about react library
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
MeteorJS Session
MeteorJS SessionMeteorJS Session
MeteorJS Session
 
Introduction to React
Introduction to ReactIntroduction to React
Introduction to React
 
Jquery dojo slides
Jquery dojo slidesJquery dojo slides
Jquery dojo slides
 

Mais de David Rodenas

Mais de David Rodenas (17)

TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDD
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: Testing
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD Techniques
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the World
 
ES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD CalculatorES3-2020-P3 TDD Calculator
ES3-2020-P3 TDD Calculator
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
 
ES3-2020-05 Testing
ES3-2020-05 TestingES3-2020-05 Testing
ES3-2020-05 Testing
 
Vespres
VespresVespres
Vespres
 
Faster web pages
Faster web pagesFaster web pages
Faster web pages
 
From high school to university and work
From high school to university and workFrom high school to university and work
From high school to university and work
 
Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1Modules in angular 2.0 beta.1
Modules in angular 2.0 beta.1
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i Enginyeria
 
Angular 1.X Community and API Decissions
Angular 1.X Community and API DecissionsAngular 1.X Community and API Decissions
Angular 1.X Community and API Decissions
 
MVS: An angular MVC
MVS: An angular MVCMVS: An angular MVC
MVS: An angular MVC
 
Mvc - Model: the great forgotten
Mvc - Model: the great forgottenMvc - Model: the great forgotten
Mvc - Model: the great forgotten
 
(automatic) Testing: from business to university and back
(automatic) Testing: from business to university and back(automatic) Testing: from business to university and back
(automatic) Testing: from business to university and back
 
Testing: ¿what, how, why?
Testing: ¿what, how, why?Testing: ¿what, how, why?
Testing: ¿what, how, why?
 

Último

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
chiefasafspells
 

Último (20)

%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
WSO2CON 2024 Slides - Unlocking Value with AI
WSO2CON 2024 Slides - Unlocking Value with AIWSO2CON 2024 Slides - Unlocking Value with AI
WSO2CON 2024 Slides - Unlocking Value with AI
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptxBUS PASS MANGEMENT SYSTEM USING PHP.pptx
BUS PASS MANGEMENT SYSTEM USING PHP.pptx
 
Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
WSO2CON 2024 - API Management Usage at La Poste and Its Impact on Business an...
 
%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto%in Soweto+277-882-255-28 abortion pills for sale in soweto
%in Soweto+277-882-255-28 abortion pills for sale in soweto
 
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open SourceWSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
WSO2CON 2024 - Freedom First—Unleashing Developer Potential with Open Source
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 

ReactJS for Programmers

  • 4. FB about MVC 4 “MVC works pretty well for small applications… but it doesn’t make room for new features.” “Flux is a single direction data flow, that avoids all the arrows going on all directions what makes really hard to understand the system.”
  • 5. FB about Chat 5 “Let’s see a real good example: FB chat” “How we get to the point, so we were annoying our users so much the just they wanted us to fix chat?” “The problems here were: • The code has no structure • It was very imperative, that makes it fragile • It loose a lot of the original intend behind it, its hard to tell what it tries [to do] • Add more features only gets this code larger • We had our most annoying chat bug happen over and over • We were always fixing some pretty good edge case, the whole system was fragile • … • This code becomes more fragile with the time. • No member of the team wanted to touch it, they wanted to jump to any other bug.”
  • 6. FB about Rendering 6 “Imperative Rendering” “If renders all each time the screen flickers” “We wanted always render all, no matter what” “Here is where React comes in.”
  • 7. FB & Virtual DOM 7
  • 11. Hello World <!-- hello-world.html --> <div id="root"></div> // hello-world.js const virtualDom = React.createElement( 'h1', null, 'Hello, world!' ); ReactDOM.render( virtualDom, document.getElementById('root') ); 11
  • 12. Hello World <!-- hello-world.html --> <div id="root"></div> // hello-world.jsx const virtualDom = <h1>Hello, world!</h1>; ReactDOM.render( virtualDom, document.getElementById('root') ); 12
  • 13. Hello World <!-- hello-world.html --> <div id="root"></div> // hello-world.jsx ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') ); 13 https://facebook.github.io/react/docs/hello-world.html
  • 14. Hello World // This is translated by Babel to... ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') ); // ...to this ReactDOM.render(React.createElement( 'h1', null, 'Hello, world!' ), document.getElementById('root')); 14 https://babeljs.io/repl
  • 15. • ReactJS only updates what changes • Although everything is regenerated every time • Open countdown example at codepen with chrome
 http://codepen.io/drpicox/pen/yMKWGN • Inspect page • You can see that only the span is updated
 (although this crude code changes everything) Do not fear change 15
  • 17. JSX // Just sugar syntax const element = <h1>Hello, world!</h1>; // It is just one object const element = React.createElement( "h1", null, "Hello, world!" ); // one object that you can manipulate as object 17
  • 18. JSX // May I? console.log(<h1>Hello!</h1>); console.log(<h1>Hello!</h1>.toString()); console.log([<h1>Hello!</h1>]); console.log({hello: <h1>Hello!</h1>}); console.log((() => <h1>Hello!</h1>)()); const salute = (what) => <h1>{what}!</h1>; console.log(salute('Hello')); 18
  • 19. JSX // Have multiple elements (but one wrapper) const element = <h1><span>Hello</span>, world!</h1>; // Generates const element = React.createElement( "h1", null, React.createElement( "span", null, "Hello" ), ", world!" ); 19
  • 20. JSX // It can be multiline (be careful using return) const element = <h1> Hello, world! </h1>; 20
  • 21. JSX // It can be multiline (better) const element = <h1> Hello, world! </h1>; 21
  • 22. JSX // It can be multiline (recommended) const element = ( <h1> Hello, world! </h1> ); 22
  • 23. JSX - Interpolation // Interpolate any JS expression const name = 'bob hoskings'; const element = ( <h1> Hello, {name}! </h1> ); // It is just one argument more const element = React.createElement( 'h1', null, 'Hello, ', name, '!' ); 23
  • 24. JSX - Interpolation // Interpolate any JS expression const user = {name:'bob', lastName:'hoskings'}; const element = ( <h1> Hello, {user.name + ' ' + user.lastName}! </h1> ); // It is still just one argument more const element = React.createElement( 'h1', null, 'Hello, ', user.name + ' ' + user.lastName, '!' ); 24
  • 25. JSX - Interpolation // any expression, including JSX const element = <h1>Hello, {<span>world</span>}!</h1> // It is still just one argument more const element = React.createElement( "h1", null, "Hello, ", React.createElement( "span", null, "world" ), "!" ); 25
  • 26. JSX - Properties // Add attributes const element = <div tabIndex="0">...</div>; // Is transformed into a property object (alias props) const element = React.createElement( "div", { tabIndex: "0" }, "..." ); 26
  • 27. JSX - Properties // Add computed attributes const element = <img src={user.imageUrl} />; // Is transformed into a property object (alias props) const element = React.createElement( "img", { src: user.imageUrl }, ); 27
  • 28. JSX - Properties // Set variable attributes const options = { autoplay: true, muted: true, }; const element = <video src="wow.mp4" {...options} />; // Are merged into attribute const element = React.createElement( "video", { src: "wow.mp4", ...options }, ); 28
  • 29. JSX - Properties // Set variable attributes const options = { autoplay: true, muted: true, }; const element = <video src="wow.mp4" {...options} />; // Are merged into attribute const element = React.createElement( "video", { src: "wow.mp4", autoplay: true, muted: true }, ); 29
  • 30. Properties vs Attributes <!-- html uses attributes --> <img id="hello" src="hello.jpg"> <!-- javascript uses properties --> const helloImg = document.getElementById('hello'); console.log(helloImg.src); 30
  • 31. Properties vs Attributes <!-- html uses attributes --> <h1 id="hello" class="big">Hello</h1> <!-- javascript uses properties --> const helloH1 = document.getElementById('hello'); console.log(helloH1.className); 31
  • 32. JSX - Properties // Because bad IE8 habits: className instead of class const element = <h1 className="big">Hello</h1>; // Is rendered as real html attribute: <h1 class="big">Hello</h1> 32
  • 33. JSX - Cross-site-scripting // It is just a string const title = response.veryMaliciousInputString; // This is save const element = <h1>{title}</h1>; 33
  • 34. JSX - XML // Is XML-like const element = ( <div> Hello <br/> World </div> ); // Elements must be terminated const element = ( <div> Hello <br> World </div> ); 34
  • 36. Rendering Elements // JSX elements are just memory objects const element = <h1>Hello, world</h1>; 36
  • 37. Rendering Elements // Given an html DOM element <div id="root"></div> // they can be rendered inside DOM const domElement = document.getElementById('root'); const reactElement = <h1>Hello, world</h1>; ReactDOM.render( reactElement, /* into */ domElement ); 37
  • 38. Rendering Elements // As many times as you want // react only updates changes const domElement = document.getElementById('root'); let n = 0; setInterval(() => { ReactDOM.render(<h1>{n += 1}</h1>, domElement); }, 1000); 38
  • 40. Components // Can be defined as functions const HelloWorld = () => { return <h1>Hello, world</h1>; }; export default HelloWorld; 40
  • 41. Components // Can be defined as functions const HelloWorld = () => { return <h1>Hello, world</h1>; }; export default HelloWorld; // Can be defined as classes export default class HelloWorld extends React.Component { render() { return <h1>Hello, world</h1>; } } 41
  • 42. Component and properties const element = <Welcome name="Dave" />; 42
  • 43. Component and properties const element = <Welcome name="Dave" />; // Remember: it is like write const element = React.createElement( Welcome, { name: "Dave" }, // are called props ); 43
  • 44. Component and properties const element = <Welcome name="Dave" />; // This is how you define the Component to use props function Welcome(props) { return ( <h1>Hello {props.name}!</h1> ); } 44
  • 45. Component and properties const element = <Welcome name="Dave" />; // This is how you define the Component to use props class Welcome extends React.Component { constructor(props) { super(props); } render() { return ( <h1>Hello {this.rops.name}!</h1> ); } } 45
  • 46. Composing Components function App() { return ( <div> <Welcome name="Alice" /> </div> ); } 46
  • 47. Composing Components function App() { return ( <div> <Welcome name="Alice" /> <Welcome name="Bob" /> <Welcome name="Dave" /> </div> ); } 47
  • 48. Refactoring Components function Component(props) { return ( <div className="Comment"> <div className="UserInfo"> <img className="Avatar" src={props.author.avatarUrl} alt={props.author.name} /> <div className="UserInfo-name"> {props.author.name} </div> </div> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formatDate(props.date)} </div> </div> ); } 48
  • 49. Refactoring Components function Avatar(props) { return ( <img className="Avatar" src={props.user.avatarUrl} alt={props.user.name} /> ); } 49 <img className="Avatar" src={props.author.avatarUrl} alt={props.author.name} />
  • 50. Refactoring Components function Component(props) { return ( <div className="Comment"> <div className="UserInfo"> <Avatar user={props.author} /> <div className="UserInfo-name"> {props.author.name} </div> </div> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formatDate(props.date)} </div> </div> ); } 50
  • 51. Refactoring Components function Component(props) { return ( <div className="Comment"> <div className="UserInfo"> <Avatar user={props.author} /> <div className="UserInfo-name"> {props.author.name} </div> </div> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formatDate(props.date)} </div> </div> ); } 51
  • 52. Refactoring Components function UserInfo(props) { return ( <div className="UserInfo"> <Avatar user={props.user} /> <div className="UserInfo-name"> {props.user.name} </div> </div> ); } 52
  • 53. Refactoring Components function Component(props) { return ( <div className="Comment"> <UserInfo user={props.author} /> <div className="Comment-text"> {props.text} </div> <div className="Comment-date"> {formatDate(props.date)} </div> </div> ); } 53
  • 54. Props are Read-Only // Render must be read-only function MissbehavingComponent(props) { return <h1>{props.n += 1}</h1>; } 54
  • 56. Function to Class Component function Clock(props) { return ( <div> <h1>Hello, world!</h1> <h2>It is {props.time}.</h2> </div> ); } 56
  • 57. Function to Class Component class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); } } 57
  • 58. Function to Class Component class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); } } 58
  • 59. Setup State class Clock extends React.Component { constructor(props) { super(props); this.state = {time: Date.now()}; } render() { ... } } 59
  • 60. Setup State class Clock extends React.Component { constructor(props) { ... } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.time}.</h2> </div> ); } } 60
  • 61. Lifecycle Methods class Clock extends React.Component { constructor(props) { ... } componentDidMount() { /* TODO */ } componentWillUnmount() { /* TODO */ } render() { ... } } 61
  • 62. Lifecycle Methods class Clock extends React.Component { constructor(props) { ... } componentDidMount() { this.timerId = setInterval( () => this.setState({time: Date.now()}), 1000 ); } componentWillUnmount() { /* TODO */ } render() { ... } } 62
  • 63. Lifecycle Methods class Clock extends React.Component { constructor(props) { ... } componentDidMount() { ... } componentWillUnmount() { clearInterval(this.timerId); } render() { ... } } 63
  • 64. setState Asynchronous // Wrong! setState({counter: this.state.counter + 1}); // Correct setState((prevState, props) => ({ counter: prevState.counter + 1 }); 64
  • 65. States are Merged constructor() { this.state = {posts: [], users: []}; } componentDidMount() { getPosts((posts) => this.setState({posts})); getUsers((users) => this.setState({users})); } 65
  • 66. State Isolated function App() { return ( <div> <Clock /> <Clock /> <Clock /> </div> ); } 66
  • 68. onEvent={fn} function ButtonLogHello() { function handleClick() { console.log('The button is clicked'); } return ( <button onClick={handleClick}> click me </button> ); } 68
  • 69. onEvent={fn} // It received the event as parameter function ALogHello() { function handleClick(ev) { ev.preventDefault(); console.log('The link is clicked'); } return ( <a href="#" onClick={handleClick}> click me </a> ); } 69
  • 70. onEvent={fn} // It can inline functions (are expressions) function DivLogHello() { return ( <button onClick={() => console.log('oh')}> click me </button> ); } 70
  • 71. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } ... 71
  • 72. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick() { ... } ... 72
  • 73. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; // This binding is necessary by `this` this.handleClick = this.handleClick.bind(this); } handleClick() { ... } ... 73
  • 74. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; // Fat arrow function preserves `this` this.handleClick = () => { ... }; } ... 74
  • 75. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } // Stage 2 alternative (recommended official) handleClick = () => { ... } ... 75
  • 76. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick = () => { … } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'on' : 'off'} </button> ); } } 76
  • 77. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick = () => { // Warning, wrong implementation this.setState({ isToggleOn: !this.state.isToggleOn }); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'on' : 'off'} </button> ); } } 77
  • 78. Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = { isToggleOn: true }; } handleClick = () => { this.setState((prevState) => ({ isToggleOn: !prevState.isToggleOn, }); } render() { return ( <button onClick={this.handleClick}> {this.state.isToggleOn ? 'on' : 'off'} </button> ); } } 78
  • 80. Conditional Rendering function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } 80
  • 81. By return function Greeting(props) { const isLoggedIn = props.isLoggedIn; if (isLoggedIn) { return <UserGreeting />; } return <GuestGreeting />; } ReactDOM.render( // Try changing to isLoggedIn={true}: <Greeting isLoggedIn={false} />, document.getElementById('root') ); 81
  • 82. By variable render() { const isLoggedIn = this.state.isLoggedIn; let button = null; if (isLoggedIn) { button = <LogoutButton onClick={this.handleLogoutClick} / >; } else { button = <LoginButton onClick={this.handleLoginClick} />; } return ( <div> <Greeting isLoggedIn={isLoggedIn} /> {button} </div> ); } 82
  • 83. By && expression function Mailbox(props) { const unreadMessages = props.unreadMessages; return ( <div> <h1>Hello!</h1> {unreadMessages.length > 0 && <h2> You have {unreadMessages.length} unread messages. </h2> } </div> ); } 83
  • 84. By ?: expression render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> {isLoggedIn ? ( <LogoutButton onClick={this.handleLogoutClick} /> ) : ( <LoginButton onClick={this.handleLoginClick} /> )} </div> ); } 84
  • 85. Prevent Render function WarningBanner(props) { if (!props.warn) { return null; } return ( <div className="warning"> Warning! </div> ); } 85
  • 87. Remember... const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map((n) => n * 2); console.log(doubled); // [2, 4, 6, 8, 10] 87
  • 88. Render Multiple // Render a reactElements array const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map((number) => <li>{number}</li> ); ReactDOM.render( <ul>{listItems}</ul>, document.getElementById('root') ); 88
  • 89. Render Multiple // Refactor into component function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li>{number}</li> ); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') ); 89
  • 90. Key function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); } 90
  • 91. Key - index const todoItems = todos.map((todo, index) => // Only do this if items have no stable IDs <li key={index}> {todo.text} </li> ); 91
  • 92. Key - Refactor Component function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); } 92
  • 93. Key - Refactor Component function ListItem(props) { return ( // Wrong! should not be here <li key="props.number.toString()"> {props.number} </li> ); } 93
  • 94. Key - Refactor Component function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => // Correct: key must remain with map <ListItem key={number.toString()} number={number} /> {number} ); return ( <ul>{listItems}</ul> ); } 94
  • 95. Key - Uniqueness // Cannot repeat keys in the same list, but... function DoubleList(props) { return ( <div> <NumberList numbers={props.numbers} /> <NumberList numbers={props.numbers} /> <NumberList numbers={props.numbers} /> </div> ); } 95
  • 96. .map inside JSX function NumberList(props) { const numbers = props.numbers; return ( <ul> {numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul> ); } 96
  • 98. Controlled Components class NameForm extends React.Component { constructor() { ... } handleChange = (event) => { this.setState({value: event.target.value}); } handleSubmit = (event) => { ... } render() { return ( <form onSubmit={this.handleSubmit}> <input type="text" value={this.state.value} onChange={this.handleChange} /> </form> ); } } 98
  • 99. Controlled Components class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; } handleChange = (event) => { ... } handleSubmit = (event) => { ... } render() { ... } } 99
  • 100. Controlled Components class NameForm extends React.Component { constructor() { ... } handleChange = (event) => { this.setState({ value: event.target.value.toLowerCase() }); } handleSubmit = (event) => { ... } render() { ... } } 100
  • 103. Multiple Inputs <input name="isGoing" type="checkbox" checked={this.state.isGoing} onChange={this.handleInputChange} /> <input name="numberOfGuests" type="number" value={this.state.numberOfGuests} onChange={this.handleInputChange} /> 103
  • 104. Multiple Inputs handleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({ [name]: value }); } 104
  • 106. Synchronizing - Consumer // We want an <input> to generate new values for function BoilingVerdict(props) { if (props.celsius >= 100) { return <p>The water would boil.</p>; } return <p>The water would not boil.</p>; } 106
  • 107. Synchronizing - Coordinator class Calculator extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: e.target.value}); render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> <BoilingVerdict celsius={parseFloat(temperature)} /> </fieldset> ); } } 107
  • 108. Synchronizing - Producer class Calculator extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: e.target.value}); render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> <BoilingVerdict celsius={parseFloat(temperature)} /> </fieldset> ); } } 108
  • 109. Synchronizing - Producer class TemperatureInputCelsius extends React.Component { constructor(props) { ... } render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 109
  • 110. Synchronizing - Producer class TemperatureInputCelsius extends React.Component { constructor(props) { ... } handleChange render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 110
  • 111. Synchronizing - Producer class TemperatureInputCelsius extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: e.target.value}); render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 111
  • 112. Synchronizing - Producer class TemperatureInputCelsius extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: e.target.value}); render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 112
  • 113. Synchronizing - Coordinator class Calculator extends React.Component { constructor(props) { ... } handleChange = (...?) => this.setState({temperature: ...?}); render() { const temperature = this.state.temperature; return ( <TemperatureInputCelsius ...? ...? /> <BoilingVerdict celsius={parseFloat(temperature)} /> </fieldset> ); } } 113
  • 114. Synchronizing - Coordinator class Calculator extends React.Component { constructor(props) { ... } handleChange = (temperature) => this.setState({temperature: temperature}); render() { const temperature = this.state.temperature; return ( <TemperatureInputCelsius temperature={temperature} onTemperatureChange={this.handleChange} /> <BoilingVerdict celsius={parseFloat(temperature)} /> </fieldset> ); } } 114
  • 115. Synchronizing - Producer class TemperatureInputCelsius extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: e.target.value}); render() { const temperature = this.state.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 115
  • 116. Synchronizing - Producer class TemperatureInputCelsius extends React.Component { constructor(props) { ... } handleChange = (e) => this.props.onTemperatureChange(e.target.value); render() { const temperature = this.props.temperature; return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 116
  • 117. Synchronizing - Coordinator 117 Calculator this: { handleChange } state: { temperature } props: { temperature } BoilingVeredict props: { temperature, onTemperatureChange } TemperatureInputCelsius
  • 118. Synchronizing - Multiple Producer Calculator TemperatureInput => Celsius and Fahrenheit 118
  • 119. Synchronizing - Producer class TemperatureInput extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: e.target.value}); render() { const temperature = this.state.temperature; const scaleName = scaleNames[this.props.scale]; return ( <fieldset> <legend>Enter temperature in {scaleName}:</ legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 119
  • 120. Synchronizing - Producer class Calculator extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: ...?}); render() { const temperature = this.state.temperature; return ( <div> <TemperatureInput scale="c" ...? ...? /> <TemperatureInput scale="f" ...? ...? /> <BoilingVerdict celsius={parseFloat(temperature)} /> </div> ); } } 120
  • 121. Synchronizing - Producer class TemperatureInput extends React.Component { constructor(props) { ... } handleChange = (e) => this.props.onTemperatureChange(e.target.value); render() { const temperature = this.props.temperature; const scaleName = scaleNames[this.props.scale]; return ( <fieldset> <legend>Enter temperature in {scaleName}:</ legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 121
  • 122. Synchronizing - Coordinator class Calculator extends React.Component { constructor(props) { ... } handleChange = (e) => this.setState({temperature: ...?}); render() { const temperature = this.state.temperature; return ( <div> <TemperatureInput scale="c" ...? ...? /> <TemperatureInput scale="f" ...? ...? /> <BoilingVerdict celsius={parseFloat(temperature)} /> </div> ); } } 122
  • 123. Coordinator - Inputs class Calculator extends React.Component { ... render() { const scale = this.state.scale; const temperature = this.state.temperature; const celsius = convertIf(scale === 'f', temperature, toCelsius); const fahrenheit = convertIf(scale === 'c', temperature, toFahrenheit); return ( <div> <TemperatureInput scale="c" temperature={celsius} ...? /> <TemperatureInput scale="f" temperature={fahrenheit} ...? /> <BoilingVerdict celsius={parseFloat(celsius)} /> </div> ); } } 123
  • 124. Coordinator Outputs class Calculator extends React.Component { ... handleCelsiusChange = (temperature) => this.setState({scale: 'c', temperature}); handleFahrenheitChange = (temperature) => this.setState({scale: 'f', temperature}); render() { const scale = this.state.scale; const temperature = this.state.temperature; const celsius = convertIf(scale === 'f', temperature, toCelsius); ... <TemperatureInput scale="c" temperature={celsius} onTemperatureChange={this.handleCelsiusChange} /> <TemperatureInput scale="f" temperature={fahrenheit} onTemperatureChange={this.handleFahrenheitChange} /> ... } } 124
  • 125. Coordinator Outputs function convertIf(test, temperature, convert) { if (test) { return tryConvert(temperature, convert); } return temperature; } 125
  • 128. Java 1.0 128 http://web.mit.edu/java_v1.0.2/www/apibook/javag2.htm An application should override the action method (II- §1.10.1) of the button or of one of its containing windows in order to cause some action to occur. Button + action(...) MyButton + action(...)
  • 129. Java 1.1 129 In 1.1, we aimed at solving some major AWT (Abstract Window Toolkit) deficiencies, with a strong focus on quality and performance. The AWT enhancements include [...], a delegation-based event model, [...]. Button + actionActionListener(...) https://www.cs.princeton.edu/courses/archive/fall97/cs461/ jdkdocs/guide/awt/index.html <i> ActionListener + actionPerformed(...) = 0 MyActionListener + actionPerformed(...) *
  • 130. Java 1.2 130 When an Action object is added to such a container, the container: Creates a component that is appropriate for that container (a toolbar creates a button component, for example), Gets the appropriate property(s) from the Action object to customize the component (for example, the icon image and flyover text).... <i> Action + actionPerformed(...) = 0 + isEnabled(): bool + setEnabled(b) + getValue(key): Object + putValue(key, value) + addPropertyChangeListener(...) + removePropertyChangeListener(...) http://www.kbs.twi.tudelft.nl/Documentation/Programming/ Java/jdk1.2/api/javax/swing/Action.html
  • 132. Children Composition <Card> <h1>Welcome</h1> <p> Find here a complete list of all the things that you love. </p> </Card> 132
  • 133. Children Composition function Card(props) { return ( <div className="card"> {props.children} </div> ); } 133
  • 135. Many Children Composition <div class="SplitPane"> <div class="SplitPane-left"> <Contacts /> </div> <div class="SplitPane-right"> <Chat /> </div> </div> 135
  • 136. Many Children Composition function SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); } 136
  • 137. Many Children Composition function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); } 137
  • 138. Specialization function Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> </FancyBorder> ); } 138
  • 139. Specialization function WelcomeDialog(props) { return ( <Dialog title="Welcome" message="Thanks for visiting!" /> ); } 139
  • 140. Specialization function WelcomeDialog(props) { return ( <Dialog title="Welcome" message={ <div> <h1>Thanks!</h1> for visiting! </div> } /> ); } 140
  • 142. Like high order functions const safeConvert = (convert) => { return (temperature) => { const input = parseFloat(temperature); if (Number.isNaN(input)) { return ''; } const output = convert(input); const rounded = Math.round(output * 100) / 100; return rounded.toString(); } } 142
  • 143. Like high order functions const safeConvert = (convert) => { return (temperature) => { ... } } const safeKelvinToCelsius = safeConvert(kelvinToCelsius); const celsius = safeKelvinToCelsius(kelvin); 143
  • 144. Specific Component class TemperatureInputCelsius extends React.Component { handleChange = (e) => this.props.onTemperatureChange( safeCelsiusToKelvin(e.target.value); ); render() { const temperature = this.props.temperature; const celsius = safeKelvinToCelsius(temperature); return ( <fieldset> <legend>Enter temperature in Celsius:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 144
  • 145. Specific Component class TemperatureInputFahrenheit extends React.Component { handleChange = (e) => this.props.onTemperatureChange( safeFahrenheitToKelvin(e.target.value); ); render() { const temperature = this.props.temperature; const celsius = safeKelvinToFahrenheit(temperature); return ( <fieldset> <legend>Enter temperature in Fahrenheit:</legend> <input value={temperature} onChange={this.handleChange} /> </fieldset> ); } } 145
  • 146. Generic Component class TemperatureInput? extends React.Component { handleChange = (e) => this.props.onTemperatureChange( toKelvin(e.target.value); ); render() { const temperature = this.props.temperature; const local = toLocal(temperature); return ( <fieldset> <legend>Enter temperature in {scaleName}:</ legend> <input value={local} onChange={this.handleChange} /> </fieldset> ); } } 146
  • 147. Generic Component function makeTemperatureInput(toKelvin, toLocal, scaleName) { return class extends React.Component { handleChange = (e) => this.props.onTemperatureChange( toKelvin(e.target.value); ); render() { const temperature = this.props.temperature; const local = toLocal(temperature); return ( <fieldset> <legend>Enter temperature in {scaleName}:</legend> <input value={local} onChange={this.handleChange} /> </fieldset> ); } } } 147
  • 148. Using Generic Component const TemperatureInputCelsius = makeTemperatureInput( safeCelsiusToKelvin, safeKelvinToCelsius, 'Celsius' ); const TemperatureInputFahrenheit = makeTemperatureInput( safeFahrenheitToKelvin, safeKelvinToFahrenheit, 'Fahrenheit' ); const TemperatureInputKelvin = makeTemperatureInput( identity, identity, 'Kelvin' ); 148
  • 149. Using Generic Component const TemperatureInputCelsius = makeTemperatureInput( safeConvert(celsiusToKelvin), safeConvert(kelvinToCelsius), 'Celsius' ); const TemperatureInputFahrenheit = makeTemperatureInput( safeConvert(fahrenheitToKelvin), safeConvert(kelvinToFahrenheit), 'Fahrenheit' ); const TemperatureInputKelvin = makeTemperatureInput( (x) => x, (x) => x, 'Kelvin' ); 149
  • 150. High Order Component class Thermostat extends React.Component { constructor(props) { ... } handleChangeMax = (e) => ... handleChangeMin = (e) => ... render() { return ( <div> Max <TemperatureInput temperature={this.state.max} onTemperatureChange={this.handleChangeMax} /> Min <TemperatureInput temperature={this.state.min} onTemperatureChange={this.handleChangeMin} /> </div> ); } } 150
  • 151. High Order Component function makeThermostat(TemperatureInput) { return class extends React.Component { constructor(props) { ... } handleChangeMax = (e) => ... handleChangeMin = (e) => ... render() { return ( <div> Max <TemperatureInput temperature={this.state.max} onTemperatureChange={this.handleChangeMax} /> Min <TemperatureInput temperature={this.state.max} onTemperatureChange={this.handleChangeMax} /> </div> ); } } } 151
  • 152. High Order Component function makeThermostat(TemperatureInput) { return class extends React.Component { ... } } const ThermostatCelsius = makeThermostat(TemperatureInputCelsius); const ThermostatFahrenheit = makeThermostat(TemperatureInputFahrenheit); const ThermostatKelvin = makeThermostat(TemperatureInputKelvin); 152
  • 153. Debug: displayName function makeTemperatureInput( toKelvin, toFahrenheit, scaleName ) { class TemperatureInput extends React.Component { ... } TemperatureInput.displayName = `TemperatureInput(${scaleName})`; return TemperatureInput; } 153
  • 154. Debug: displayName function makeThermostat(TemperatureInput) { class Thermostat extends React.Component { ... } Thermostat.displayName = `Thermostat(${getDisplayName(TemperatureInput)})`; return Thermostat; } 154
  • 155. Warning! // DON'T use HOCs in render functions! const App = () => { const TemperatureInputAbc = makeTemperatureInput(a, b, c); return <TemperatureInputAbc />; } class App extends React.Component { render() { const TemperatureInputAbc = makeTemperatureInput(a, b, c); return <TemperatureInputAbc />; } } 155
  • 156. More in docs • Use HOCs For Cross-Cutting Concerns • Don't Mutate the Original Component. 
 Use Composition. • Convention: Pass Unrelated Props Through to the Wrapped Component • Convention: Maximizing Composability • Convention: Wrap the Display Name for Easy Debugging • Caveats 156
  • 158. Convention • Types of components • Routers • Containers • Presentational 158
  • 159. Routes • Routers • Decides which component to render • Create components dynamically • Usually provided by library 159
  • 160. Containers • Knows how to load or mutate data • Observe Stores • Dispatch Actions • Other system interactions • Always stateful (class notation) • Renders nothing • Delegates render to a Presentational Component • Configures its props 160
  • 161. Presentational • Knows how to render things • Data and callbacks only via props • does not interact with the application • Usually functional (not need state) • Also called Components 161
  • 162. class Clock extends React.Component { constructor(props) { ... } componentDidMount() { this.timerId = setInterval( () => this.setState({time: Date.now()}), 1000 ); } componentWillUnmount() { clearInterval(this.timerId); } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.time}.</h2> </div> ); } } 162 Presentational Container
  • 163. class Clock extends React.Component { constructor(props) { ... } componentDidMount() { this.timerId = setInterval( () => this.setState({time: Date.now()}), 1000 ); } componentWillUnmount() { clearInterval(this.timerId); } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.time}.</h2> </div> ); } } 163 Presentational Container
  • 164. Presentational Refactor function Clock(props) { return ( <div> <h1>Hello, world!</h1> <h2>It is {props.time}.</h2> </div> ); } 164
  • 165. Container Refactor class IntervalClock extends React.Component { constructor(props) { ... } componentDidMount() { this.timerId = setInterval( () => this.setState({time: Date.now()}), 1000 ); } componentWillUnmount() { clearInterval(this.timerId); } render() { return <Clock time={this.state.time} />; } } 165
  • 166. Container Refactor function makeIntervalClock(Clock) { return class extends React.Component { constructor(props) { ... } componentDidMount() { this.timerId = setInterval( () => this.setState({time: Date.now()}), 1000 ); } componentWillUnmount() { clearInterval(this.timerId); } render() { return <Clock time={this.state.time} />; } }; } 166
  • 168. PropTypes import PropTypes from 'prop-types'; export default function Welcome(props) { return ( <h1>Hello, {props.name}</h1> ); } Welcome.propTypes = { name: PropTypes.string }; 168 https://facebook.github.io/react/docs/typechecking-with-proptypes.html
  • 169. PropTypes import PropTypes from 'prop-types'; export default class Welcome extends React.Component { render() { return ( <h1>Hello, {this.props.name}</h1> ); } } Welcome.propTypes = { name: PropTypes.string.isRequired }; 169 https://facebook.github.io/react/docs/typechecking-with-proptypes.html