SlideShare a Scribd company logo
Basic ReactJS
for Programmers
by Dr. David Rodenas
Origin
@drpicox
FB about MVC
3
https://youtu.be/nYkdrAPrdcw?t=10m20s
2014
@drpicox
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.”
@drpicox
FB about MVC
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.”
@drpicox
FB about MVC
6
flux
@drpicox
FB about Rendering
7
“Imperative Rendering”
“If renders all each time
the screen flickers”
“We wanted always render all, no matter what”
“Here is where React comes in.”
ReactJS
@drpicox
Prerequisite
Make an account in codepen.io
@drpicox
Prerequisite
Install React Developer Tools
Basics
@drpicox
Hello World
<!-- hello-world.html -->
<div id="root"></div>
// hello-world.js
ReactDOM.render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
12
https://facebook.github.io/react/docs/hello-world.html
@drpicox
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'));
13
https://babeljs.io/repl
@drpicox
Do not fear change
• ReactJS only updates what changes
• Although everything is regenerated every time
• Open countdown example at codepen with chrome

http://codepen.io/drpicox/pen/yMKWGN
• Change View > Debug Mode (only works if registered)
• Inspect page
• You can see that only the span is updated

(although this crude code changes everything)
14
JSX
https://facebook.github.io/react/docs/introducing-jsx.html
@drpicox
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
16
@drpicox
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'));
17
@drpicox
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!"
);
18
@drpicox
JSX
// It can be multiline (be careful using return)
const element =
<h1>
Hello, world!
</h1>;
19
@drpicox
JSX
// It can be multiline (better)
const element = <h1>
Hello, world!
</h1>;
20
@drpicox
JSX
// It can be multiline (recommended)
const element = (
<h1>
Hello, world!
</h1>
);
21
@drpicox
JSX
// Interpolate any JS expression
const user = {name:'bob', lastName:'hoskings'};
const element = (
<h1>
Hello, {user.name + ' ' + user.lastName}!
</h1>
);
// any expression, including JSX
const element = <h1>Hello, {<span>world</span>}!
22
@drpicox
JSX
// Add attributes (alias props)
const element = <div tabIndex="0">...</div>;
// Computed attributes
const element = <img src={user.imageUrl} />;
// class is className
const element = <div className="body">...</div>;
23
@drpicox
JSX - Cross-site-scripting
// It is just a string
const title = response.veryMaliciousInput;
// This is save
const element = <h1>{title}</h1>;
24
@drpicox
JSX
// Is XML-like
const element = (
<div>
Hello <br/> World
</div>
);
// Elements must be terminated
const element = (
<div>
Hello <br> World
</div>
);
25
Rendering Elements
https://facebook.github.io/react/docs/rendering-elements.html
@drpicox
Rendering Elements
// JSX elements are just memory objects
const element = <h1>Hello, world</h1>;
27
@drpicox
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
);
28
@drpicox
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);
29
Components and Props
https://facebook.github.io/react/docs/components-and-props.html
@drpicox
Component definition
// Functional component
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
// Class component
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
31
@drpicox
Render a Component
const element = <Welcome name="Dave" />;
32
@drpicox
Composing Components
function App() {
return (
<div>
<Welcome name="Alice" />
<Welcome name="Bob" />
<Welcome name="Dave" />
</div>
);
}
33
@drpicox
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>
);
}
34
@drpicox
Refactoring Components
function Avatar(props) {
return (
<img className="Avatar"
src={props.user.avatarUrl}
alt={props.user.name}
/>
);
}
35
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
@drpicox
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>
);
}
36
@drpicox
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>
);
}
37
@drpicox
Refactoring Components
function UserInfo(props) {
return (
<div className="UserInfo">
<Avatar user={props.user} />
<div className="UserInfo-name">
{props.user.name}
</div>
</div>
);
}
38
@drpicox
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>
);
}
39
@drpicox
Props are Read-Only
// Render must be read-only
function MissbehavingComponent(props) {
return <h1>{props.n += 1}</h1>;
}
40
State and Lifecycle
https://facebook.github.io/react/docs/state-and-lifecycle.html
@drpicox
Function to Class Component
function Clock(props) {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {props.time}.</h2>
</div>
);
}
42
@drpicox
Function to Class Component
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.time}.</h2>
</div>
);
}
}
43
@drpicox
Function to Class Component
class Clock extends React.Component {
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.time}.</h2>
</div>
);
}
}
44
@drpicox
Setup State
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = {time: Date.now()};
}
render() { ... }
}
45
@drpicox
Setup State
class Clock extends React.Component {
constructor(props) { ... }
render() {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.state.time}.</h2>
</div>
);
}
}
46
@drpicox
Lifecycle Methods
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() { /* TODO */ }
componentWillUnmount() { /* TODO */ }
render() { ... }
}
47
@drpicox
Lifecycle Methods
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() {
this.timerId = setInterval(
() => this.setState({time: Date.now()}),
1000
);
}
componentWillUnmount() { /* TODO */ }
render() { ... }
}
48
@drpicox
Lifecycle Methods
class Clock extends React.Component {
constructor(props) { ... }
componentDidMount() { ... }
componentWillUnmount() {
clearInterval(this.timerId);
}
render() { ... }
}
49
@drpicox
setState Asynchronous
// Wrong!
setState({counter: this.state.counter + 1});
// Correct
setState((prevState, props) => ({
counter: prevState.counter + 1
});
50
@drpicox
States are Merged
constructor() {
this.state = {posts: [], users: []};
}
componentDidMount() {
getPosts((posts) => this.setState({posts}));
getUsers((users) => this.setState({users}));
}
51
@drpicox
State Isolated
function App() {
return (
<div>
<Clock />
<Clock />
<Clock />
</div>
);
}
52
Handling Events
@drpicox
onEvent={fn}
function ButtonLogHello() {
function handleClick() {
console.log('The button is clicked');
}
return (
<button onClick={handleClick}>
click me
</button>
);
}
54
@drpicox
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>
);
}
55
@drpicox
onEvent={fn}
// It can inline functions (are expressions)
function DivLogHello() {
return (
<button onClick={() => console.log('oh')}>
click me
</button>
);
}
56
@drpicox
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() { ... }
...
57
https://facebook.github.io/react/docs/handling-events.html
@drpicox
Toggle Example
class Toggle extends React.Component {
constructor(props) {
super(props);
this.state = {isToggleOn: true};
}
handleClick = () => { ... }
...
58
https://facebook.github.io/react/docs/handling-events.html
Conditional Rendering
https://facebook.github.io/react/docs/conditional-rendering.html
@drpicox
Conditional Rendering
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
60
@drpicox
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')
);
61
@drpicox
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>
);
}
62
@drpicox
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>
);
}
63
@drpicox
By ?: expression
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
{isLoggedIn ? (
<LogoutButton onClick={this.handleLogoutClick} />
) : (
<LoginButton onClick={this.handleLoginClick} />
)}
</div>
);
}
64
@drpicox
Prevent Render
function WarningBanner(props) {
if (!props.warn) {
return null;
}
return (
<div className="warning">
Warning!
</div>
);
}
65
Lists and Keys
@drpicox
Remember...
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((n) => n * 2);
console.log(doubled);
// [2, 4, 6, 8, 10]
67
@drpicox
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')
);
68
@drpicox
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')
);
69
@drpicox
Key
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
70
@drpicox
Key - index
const todoItems = todos.map((todo, index) =>
// Only do this if items have no stable IDs
<li key={index}>
{todo.text}
</li>
);
71
@drpicox
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>
);
}
72
@drpicox
Key - Refactor Component
function ListItem(props) {
return (
// Wrong! should not be here
<li key="props.number.toString()">
{props.number}
</li>
);
}
73
@drpicox
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>
);
}
74
@drpicox
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>
);
}
75
@drpicox
.map inside JSX
function NumberList(props) {
const numbers = props.numbers;
return (
<ul>
{numbers.map((number) =>
<ListItem key={number.toString()}
value={number} />
)}
</ul>
);
}
76
Forms
@drpicox
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>
);
}
}
78
@drpicox
Controlled Components
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {value: ''};
}
handleChange = (event) => { ... }
handleSubmit = (event) => { ... }
render() { ... }
}
79
@drpicox
Controlled Components
class NameForm extends React.Component {
constructor() { ... }
handleChange = (event) => {
this.setState({
value: event.target.value.toLowerCase()
});
}
handleSubmit = (event) => { ... }
render() { ... }
}
80
@drpicox
Textarea
<textarea
value={this.state.value}
onChange={this.handleChange}
/>
81
@drpicox
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>
82
@drpicox
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} />
83
@drpicox
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
});
}
84
Synchronized States
https://facebook.github.io/react/docs/lifting-state-up.html
@drpicox
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>;
}
86
@drpicox
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>
);
}
}
87
@drpicox
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>
);
}
}
88
@drpicox
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>
);
}
}
89
@drpicox
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>
);
}
}
90
@drpicox
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>
);
}
}
91
@drpicox
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>
);
}
}
92
@drpicox
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>
);
}
}
93
@drpicox
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} />
...
}
}
94
@drpicox
Coordinator Outputs
function convertIf(test, temperature, convert) {
if (test) {
return tryConvert(temperature, convert);
}
return temperature;
}
95
@drpicox
Exercise
96
https://codepen.io/drpicox/pen/ryrypJ
Exercise React Temperature
Component Composition
https://facebook.github.io/react/docs/composition-vs-
inheritance.html
@drpicox
Java 1.0
98
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(...)
@drpicox
Java 1.1
99
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(...)
*
@drpicox
Java 1.2
100
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
@drpicox
Children Composition
101
Card
Contents
@drpicox
Children Composition
<card>
<h1>Welcome</h1>
<p>
Find here a complete list
of all the things that you
love.
</p>
</card>
102
@drpicox
Children Composition
function Card(props) {
return (
<div className="card">
{props.children}
</div>
);
}
103
@drpicox
Many Children Composition
104
SplitPane
Left Right
@drpicox
Many Children Composition
<div class="SplitPane">
<div class="SplitPane-left">
<Contacts />
</div>
<div class="SplitPane-left">
<Chat />
</div>
</div>
105
@drpicox
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>
);
}
106
@drpicox
Many Children Composition
function App() {
return (
<SplitPane
left={ <Contacts /> }
right={ <Chat /> }
/>
);
}
107
@drpicox
Specialization
function Dialog(props) {
return (
<FancyBorder color="blue">
<h1 className="Dialog-title">
{props.title}
</h1>
<p className="Dialog-message">
{props.message}
</p>
</FancyBorder>
);
}
108
@drpicox
Specialization
function WelcomeDialog(props) {
return (
<Dialog
title="Welcome"
message="Thanks for visiting!" />
);
}
109
High Order Components (I)
https://facebook.github.io/react/docs/higher-order-
components.html
@drpicox
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();
}
}
111
@drpicox
Like high order functions
const safeConvert = (convert) => {
return (temperature) => {
...
}
}
const safeKelvinToCelsius =
safeConvert(kelvinToCelsius);
const celsius = safeKelvinToCelsius(kelvin);
112
@drpicox
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>
);
}
} 113
@drpicox
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>
);
}
} 114
@drpicox
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>
);
}
} 115
@drpicox
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>
);
}
}
}
116
@drpicox
Using Generic Component
const TemperatureInputCelsius = makeTemperatureInput(
safeCelsiusToKelvin,
safeKelvinToCelsius,
'Celsius'
);
const TemperatureInputFahrenheit = makeTemperatureInput(
safeFahrenheitToKelvin,
safeKelvinToFahrenheit,
'Fahrenheit'
);
const TemperatureInputKelvin = makeTemperatureInput(
identity,
identity,
'Kelvin'
); 117
@drpicox
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'
); 118
@drpicox
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>
);
}
}
119
@drpicox
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>
);
}
}
} 120
@drpicox
High Order Component
function makeThermostat(TemperatureInput) {
return class extends React.Component {
...
}
}
const ThermostatCelsius =
makeThermostat(TemperatureInputCelsius);
const ThermostatFahrenheit =
makeThermostat(TemperatureInputFahrenheit);
const ThermostatKelvin =
makeThermostat(TemperatureInputKelvin); 121
@drpicox
Debug: displayName
function makeTemperatureInpu(
toKelvin, toFahrenheit, scaleName
) {
class TemperatureInput extends React.Component {
...
}
TemperatureInput.displayName =
`TemperatureInput(${scaleName})`;
return TemperatureInput;
}
122
@drpicox
Debug: displayName
function makeThermostat(TemperatureInput) {
class Thermostat extends React.Component {
...
}
Thermostat.displayName =
`Thermostat(${getDisplayName(TemperatureInput)})`;
return Thermostat;
}
123
@drpicox
Warning
// DON'T use HOCs in render functions!
function App() {
const TemperatureInputAbc =
makeTemperatureInput(a, b, c);
return <TemperatureInputAbc />;
}
class App extends React.Component {
render() {
const TemperatureInputAbc =
makeTemperatureInput(a, b, c);
return <TemperatureInputAbc />;
}
}
124
@drpicox
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
125
Containers
https://medium.com/@dan_abramov/smart-and-dumb-
components-7ca2f9a7c7d0
@drpicox
Convention
• Types of components
• Routers
• Containers
• Presentational
127
@drpicox
Routes
• Routers
• Decides which component to render
• Create components dynamically
• Usually provided by library
128
@drpicox
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
129
@drpicox
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
130
@drpicox
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>
);
}
}
131
Presentational
Container
@drpicox
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>
);
}
}
132
Presentational
Container
@drpicox
Presentational Refactor
function Clock {
return (
<div>
<h1>Hello, world!</h1>
<h2>It is {this.props.time}.</h2>
</div>
);
}
133
@drpicox
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} />;
}
}
134

More Related Content

What's hot

React
React React
React
중운 박
 
Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limitsDroidcon Berlin
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
rstankov
 
React js
React jsReact js
Why ruby
Why rubyWhy ruby
Why ruby
rstankov
 
Backbone js
Backbone jsBackbone js
Backbone js
rstankov
 
Getting started with ReactJS
Getting started with ReactJSGetting started with ReactJS
Getting started with ReactJS
Krishna Sunuwar
 
React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7
Dongho Cho
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widget
Tudor Barbu
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
Siarhei Barysiuk
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
Visual Engineering
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KThomas Fuchs
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
Natasha Murashev
 
meet.js - QooXDoo
meet.js - QooXDoomeet.js - QooXDoo
meet.js - QooXDoo
Radek Benkel
 
"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald Pehl"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald Pehl
GWTcon
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todaygerbille
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
Katy Slemon
 
jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Eventsdmethvin
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
jnewmanux
 

What's hot (20)

React
React React
React
 
Android programming -_pushing_the_limits
Android programming -_pushing_the_limitsAndroid programming -_pushing_the_limits
Android programming -_pushing_the_limits
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
React js
React jsReact js
React js
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Backbone js
Backbone jsBackbone js
Backbone js
 
Getting started with ReactJS
Getting started with ReactJSGetting started with ReactJS
Getting started with ReactJS
 
React, Redux and es6/7
React, Redux and es6/7React, Redux and es6/7
React, Redux and es6/7
 
Building a js widget
Building a js widgetBuilding a js widget
Building a js widget
 
JavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best PracticesJavaScript and UI Architecture Best Practices
JavaScript and UI Architecture Best Practices
 
Workshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScriptWorkshop 1: Good practices in JavaScript
Workshop 1: Good practices in JavaScript
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
 
meet.js - QooXDoo
meet.js - QooXDoomeet.js - QooXDoo
meet.js - QooXDoo
 
"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald Pehl"Migrate large gwt applications - Lessons Learned" By Harald Pehl
"Migrate large gwt applications - Lessons Learned" By Harald Pehl
 
Creating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of todayCreating the interfaces of the future with the APIs of today
Creating the interfaces of the future with the APIs of today
 
How to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescriptHow to build to do app using vue composition api and vuex 4 with typescript
How to build to do app using vue composition api and vuex 4 with typescript
 
jQuery 1.7 Events
jQuery 1.7 EventsjQuery 1.7 Events
jQuery 1.7 Events
 
Dan Webb Presentation
Dan Webb PresentationDan Webb Presentation
Dan Webb Presentation
 
Understanding Asynchronous JavaScript
Understanding Asynchronous JavaScriptUnderstanding Asynchronous JavaScript
Understanding Asynchronous JavaScript
 

Similar to Basic Tutorial of React for Programmers

ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
David Rodenas
 
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]
GDSC UofT Mississauga
 
Jquery dojo slides
Jquery dojo slidesJquery dojo slides
Jquery dojo slideshelenmga
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
Mike Wilcox
 
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...
Luciano Mammino
 
React mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche EheReact mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche Ehe
inovex GmbH
 
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
Matteo Manchi
 
React js
React jsReact js
React js
Rajesh Kolla
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
Hassan Abid
 
Web Components With Rails
Web Components With RailsWeb Components With Rails
Web Components With Rails
Boris Nadion
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React NativeLessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
Ryan Boland
 
The Exciting Future Of React
The Exciting Future Of ReactThe Exciting Future Of React
The Exciting Future Of React
kristijanmkd
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
Siarzh Miadzvedzeu
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Mark Proctor
 
The Gist of React Native
The Gist of React NativeThe Gist of React Native
The Gist of React Native
Darren Cruse
 
React - Start learning today
React - Start learning today React - Start learning today
React - Start learning today
Nitin Tyagi
 
AFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack EncoreAFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack Encore
Engineor
 
Let's react - Meetup
Let's react - MeetupLet's react - Meetup
Let's react - Meetup
RAJNISH KATHAROTIYA
 
5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)
Christian Rokitta
 

Similar to Basic Tutorial of React for Programmers (20)

ReactJS for Programmers
ReactJS for ProgrammersReactJS for Programmers
ReactJS for Programmers
 
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]
 
Jquery dojo slides
Jquery dojo slidesJquery dojo slides
Jquery dojo slides
 
Web Components v1
Web Components v1Web Components v1
Web Components v1
 
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...
 
React mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche EheReact mit TypeScript – eine glückliche Ehe
React mit TypeScript – eine glückliche Ehe
 
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
 
ReactJS.ppt
ReactJS.pptReactJS.ppt
ReactJS.ppt
 
React js
React jsReact js
React js
 
Building Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture ComponentsBuilding Modern Apps using Android Architecture Components
Building Modern Apps using Android Architecture Components
 
Web Components With Rails
Web Components With RailsWeb Components With Rails
Web Components With Rails
 
Lessons from a year of building apps with React Native
Lessons from a year of building apps with React NativeLessons from a year of building apps with React Native
Lessons from a year of building apps with React Native
 
The Exciting Future Of React
The Exciting Future Of ReactThe Exciting Future Of React
The Exciting Future Of React
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client TechnologyRed Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
Red Hat JBoss BRMS and BPMS Workbench and Rich Client Technology
 
The Gist of React Native
The Gist of React NativeThe Gist of React Native
The Gist of React Native
 
React - Start learning today
React - Start learning today React - Start learning today
React - Start learning today
 
AFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack EncoreAFUP Lorraine - Symfony Webpack Encore
AFUP Lorraine - Symfony Webpack Encore
 
Let's react - Meetup
Let's react - MeetupLet's react - Meetup
Let's react - Meetup
 
5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)5 x HTML5 worth using in APEX (5)
5 x HTML5 worth using in APEX (5)
 

More from David Rodenas

TDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDDTDD CrashCourse Part2: TDD
TDD CrashCourse Part2: TDD
David Rodenas
 
TDD CrashCourse Part1: Testing
TDD CrashCourse Part1: TestingTDD CrashCourse Part1: Testing
TDD CrashCourse Part1: Testing
David Rodenas
 
TDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD TechniquesTDD CrashCourse Part3: TDD Techniques
TDD CrashCourse Part3: TDD Techniques
David Rodenas
 
TDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing TechniquesTDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing Techniques
David Rodenas
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving Testing
David Rodenas
 
Be professional: We Rule the World
Be professional: We Rule the WorldBe professional: We Rule the World
Be professional: We Rule the World
David Rodenas
 
ES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
David Rodenas
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniques
David Rodenas
 
ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)
David Rodenas
 
ES3-2020-05 Testing
ES3-2020-05 TestingES3-2020-05 Testing
ES3-2020-05 Testing
David Rodenas
 
Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214
David Rodenas
 
Vespres
VespresVespres
Vespres
David Rodenas
 
Faster web pages
Faster web pagesFaster web pages
Faster web pages
David Rodenas
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
David Rodenas
 
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
David Rodenas
 
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
David Rodenas
 
Freelance i Enginyeria
Freelance i EnginyeriaFreelance i Enginyeria
Freelance i Enginyeria
David Rodenas
 
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
David Rodenas
 
JS and patterns
JS and patternsJS and patterns
JS and patterns
David Rodenas
 
MVS: An angular MVC
MVS: An angular MVCMVS: An angular MVC
MVS: An angular MVC
David Rodenas
 

More from David Rodenas (20)

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
 
TDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing TechniquesTDD CrashCourse Part5: Testing Techniques
TDD CrashCourse Part5: Testing Techniques
 
TDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving TestingTDD CrashCourse Part4: Improving Testing
TDD CrashCourse Part4: Improving Testing
 
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-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game KataES3-2020-P2 Bowling Game Kata
ES3-2020-P2 Bowling Game Kata
 
ES3-2020-07 Testing techniques
ES3-2020-07 Testing techniquesES3-2020-07 Testing techniques
ES3-2020-07 Testing techniques
 
ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)ES3-2020-06 Test Driven Development (TDD)
ES3-2020-06 Test Driven Development (TDD)
 
ES3-2020-05 Testing
ES3-2020-05 TestingES3-2020-05 Testing
ES3-2020-05 Testing
 
Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214Testing, Learning and Professionalism — 20171214
Testing, Learning and Professionalism — 20171214
 
Vespres
VespresVespres
Vespres
 
Faster web pages
Faster web pagesFaster web pages
Faster web pages
 
Introduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicoxIntroduction to web programming for java and c# programmers by @drpicox
Introduction to web programming for java and c# programmers by @drpicox
 
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
 
JS and patterns
JS and patternsJS and patterns
JS and patterns
 
MVS: An angular MVC
MVS: An angular MVCMVS: An angular MVC
MVS: An angular MVC
 

Recently uploaded

Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Natan Silnitsky
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
Matt Welsh
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
Globus
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Globus
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
Cyanic lab
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus
 
De mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FMEDe mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FME
Jelle | Nordend
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
vrstrong314
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Anthony Dahanne
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
Paco van Beckhoven
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
WSO2
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
Georgi Kodinov
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
Tendenci - The Open Source AMS (Association Management Software)
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
Max Andersen
 

Recently uploaded (20)

Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.ILBeyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
Beyond Event Sourcing - Embracing CRUD for Wix Platform - Java.IL
 
Large Language Models and the End of Programming
Large Language Models and the End of ProgrammingLarge Language Models and the End of Programming
Large Language Models and the End of Programming
 
Understanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSageUnderstanding Globus Data Transfers with NetSage
Understanding Globus Data Transfers with NetSage
 
Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...Developing Distributed High-performance Computing Capabilities of an Open Sci...
Developing Distributed High-performance Computing Capabilities of an Open Sci...
 
Cyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdfCyaniclab : Software Development Agency Portfolio.pdf
Cyaniclab : Software Development Agency Portfolio.pdf
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024Globus Connect Server Deep Dive - GlobusWorld 2024
Globus Connect Server Deep Dive - GlobusWorld 2024
 
De mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FMEDe mooiste recreatieve routes ontdekken met RouteYou en FME
De mooiste recreatieve routes ontdekken met RouteYou en FME
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
top nidhi software solution freedownload
top nidhi software solution freedownloadtop nidhi software solution freedownload
top nidhi software solution freedownload
 
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
Paketo Buildpacks : la meilleure façon de construire des images OCI? DevopsDa...
 
Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024Cracking the code review at SpringIO 2024
Cracking the code review at SpringIO 2024
 
Accelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with PlatformlessAccelerate Enterprise Software Engineering with Platformless
Accelerate Enterprise Software Engineering with Platformless
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx2024 RoOUG Security model for the cloud.pptx
2024 RoOUG Security model for the cloud.pptx
 
Corporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMSCorporate Management | Session 3 of 3 | Tendenci AMS
Corporate Management | Session 3 of 3 | Tendenci AMS
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
Quarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden ExtensionsQuarkus Hidden and Forbidden Extensions
Quarkus Hidden and Forbidden Extensions
 

Basic Tutorial of React for Programmers

  • 4. @drpicox 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. @drpicox FB about MVC 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.”
  • 7. @drpicox FB about Rendering 7 “Imperative Rendering” “If renders all each time the screen flickers” “We wanted always render all, no matter what” “Here is where React comes in.”
  • 12. @drpicox Hello World <!-- hello-world.html --> <div id="root"></div> // hello-world.js ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') ); 12 https://facebook.github.io/react/docs/hello-world.html
  • 13. @drpicox 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')); 13 https://babeljs.io/repl
  • 14. @drpicox Do not fear change • ReactJS only updates what changes • Although everything is regenerated every time • Open countdown example at codepen with chrome
 http://codepen.io/drpicox/pen/yMKWGN • Change View > Debug Mode (only works if registered) • Inspect page • You can see that only the span is updated
 (although this crude code changes everything) 14
  • 16. @drpicox 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 16
  • 17. @drpicox 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')); 17
  • 18. @drpicox 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!" ); 18
  • 19. @drpicox JSX // It can be multiline (be careful using return) const element = <h1> Hello, world! </h1>; 19
  • 20. @drpicox JSX // It can be multiline (better) const element = <h1> Hello, world! </h1>; 20
  • 21. @drpicox JSX // It can be multiline (recommended) const element = ( <h1> Hello, world! </h1> ); 21
  • 22. @drpicox JSX // Interpolate any JS expression const user = {name:'bob', lastName:'hoskings'}; const element = ( <h1> Hello, {user.name + ' ' + user.lastName}! </h1> ); // any expression, including JSX const element = <h1>Hello, {<span>world</span>}! 22
  • 23. @drpicox JSX // Add attributes (alias props) const element = <div tabIndex="0">...</div>; // Computed attributes const element = <img src={user.imageUrl} />; // class is className const element = <div className="body">...</div>; 23
  • 24. @drpicox JSX - Cross-site-scripting // It is just a string const title = response.veryMaliciousInput; // This is save const element = <h1>{title}</h1>; 24
  • 25. @drpicox JSX // Is XML-like const element = ( <div> Hello <br/> World </div> ); // Elements must be terminated const element = ( <div> Hello <br> World </div> ); 25
  • 27. @drpicox Rendering Elements // JSX elements are just memory objects const element = <h1>Hello, world</h1>; 27
  • 28. @drpicox 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 ); 28
  • 29. @drpicox 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); 29
  • 31. @drpicox Component definition // Functional component function Welcome(props) { return <h1>Hello, {props.name}</h1>; } // Class component class Welcome extends React.Component { render() { return <h1>Hello, {this.props.name}</h1>; } } 31
  • 32. @drpicox Render a Component const element = <Welcome name="Dave" />; 32
  • 33. @drpicox Composing Components function App() { return ( <div> <Welcome name="Alice" /> <Welcome name="Bob" /> <Welcome name="Dave" /> </div> ); } 33
  • 34. @drpicox 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> ); } 34
  • 35. @drpicox Refactoring Components function Avatar(props) { return ( <img className="Avatar" src={props.user.avatarUrl} alt={props.user.name} /> ); } 35 <img className="Avatar" src={props.author.avatarUrl} alt={props.author.name} />
  • 36. @drpicox 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> ); } 36
  • 37. @drpicox 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> ); } 37
  • 38. @drpicox Refactoring Components function UserInfo(props) { return ( <div className="UserInfo"> <Avatar user={props.user} /> <div className="UserInfo-name"> {props.user.name} </div> </div> ); } 38
  • 39. @drpicox 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> ); } 39
  • 40. @drpicox Props are Read-Only // Render must be read-only function MissbehavingComponent(props) { return <h1>{props.n += 1}</h1>; } 40
  • 42. @drpicox Function to Class Component function Clock(props) { return ( <div> <h1>Hello, world!</h1> <h2>It is {props.time}.</h2> </div> ); } 42
  • 43. @drpicox Function to Class Component class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); } } 43
  • 44. @drpicox Function to Class Component class Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); } } 44
  • 45. @drpicox Setup State class Clock extends React.Component { constructor(props) { super(props); this.state = {time: Date.now()}; } render() { ... } } 45
  • 46. @drpicox Setup State class Clock extends React.Component { constructor(props) { ... } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.time}.</h2> </div> ); } } 46
  • 47. @drpicox Lifecycle Methods class Clock extends React.Component { constructor(props) { ... } componentDidMount() { /* TODO */ } componentWillUnmount() { /* TODO */ } render() { ... } } 47
  • 48. @drpicox Lifecycle Methods class Clock extends React.Component { constructor(props) { ... } componentDidMount() { this.timerId = setInterval( () => this.setState({time: Date.now()}), 1000 ); } componentWillUnmount() { /* TODO */ } render() { ... } } 48
  • 49. @drpicox Lifecycle Methods class Clock extends React.Component { constructor(props) { ... } componentDidMount() { ... } componentWillUnmount() { clearInterval(this.timerId); } render() { ... } } 49
  • 50. @drpicox setState Asynchronous // Wrong! setState({counter: this.state.counter + 1}); // Correct setState((prevState, props) => ({ counter: prevState.counter + 1 }); 50
  • 51. @drpicox States are Merged constructor() { this.state = {posts: [], users: []}; } componentDidMount() { getPosts((posts) => this.setState({posts})); getUsers((users) => this.setState({users})); } 51
  • 52. @drpicox State Isolated function App() { return ( <div> <Clock /> <Clock /> <Clock /> </div> ); } 52
  • 54. @drpicox onEvent={fn} function ButtonLogHello() { function handleClick() { console.log('The button is clicked'); } return ( <button onClick={handleClick}> click me </button> ); } 54
  • 55. @drpicox 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> ); } 55
  • 56. @drpicox onEvent={fn} // It can inline functions (are expressions) function DivLogHello() { return ( <button onClick={() => console.log('oh')}> click me </button> ); } 56
  • 57. @drpicox 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() { ... } ... 57 https://facebook.github.io/react/docs/handling-events.html
  • 58. @drpicox Toggle Example class Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; } handleClick = () => { ... } ... 58 https://facebook.github.io/react/docs/handling-events.html
  • 60. @drpicox Conditional Rendering function UserGreeting(props) { return <h1>Welcome back!</h1>; } function GuestGreeting(props) { return <h1>Please sign up.</h1>; } 60
  • 61. @drpicox 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') ); 61
  • 62. @drpicox 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> ); } 62
  • 63. @drpicox 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> ); } 63
  • 64. @drpicox By ?: expression render() { const isLoggedIn = this.state.isLoggedIn; return ( <div> {isLoggedIn ? ( <LogoutButton onClick={this.handleLogoutClick} /> ) : ( <LoginButton onClick={this.handleLoginClick} /> )} </div> ); } 64
  • 65. @drpicox Prevent Render function WarningBanner(props) { if (!props.warn) { return null; } return ( <div className="warning"> Warning! </div> ); } 65
  • 67. @drpicox Remember... const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map((n) => n * 2); console.log(doubled); // [2, 4, 6, 8, 10] 67
  • 68. @drpicox 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') ); 68
  • 69. @drpicox 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') ); 69
  • 70. @drpicox Key function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); } 70
  • 71. @drpicox Key - index const todoItems = todos.map((todo, index) => // Only do this if items have no stable IDs <li key={index}> {todo.text} </li> ); 71
  • 72. @drpicox 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> ); } 72
  • 73. @drpicox Key - Refactor Component function ListItem(props) { return ( // Wrong! should not be here <li key="props.number.toString()"> {props.number} </li> ); } 73
  • 74. @drpicox 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> ); } 74
  • 75. @drpicox 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> ); } 75
  • 76. @drpicox .map inside JSX function NumberList(props) { const numbers = props.numbers; return ( <ul> {numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul> ); } 76
  • 77. Forms
  • 78. @drpicox 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> ); } } 78
  • 79. @drpicox Controlled Components class NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; } handleChange = (event) => { ... } handleSubmit = (event) => { ... } render() { ... } } 79
  • 80. @drpicox Controlled Components class NameForm extends React.Component { constructor() { ... } handleChange = (event) => { this.setState({ value: event.target.value.toLowerCase() }); } handleSubmit = (event) => { ... } render() { ... } } 80
  • 83. @drpicox 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} /> 83
  • 84. @drpicox 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 }); } 84
  • 86. @drpicox 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>; } 86
  • 87. @drpicox 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> ); } } 87
  • 88. @drpicox 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> ); } } 88
  • 89. @drpicox 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> ); } } 89
  • 90. @drpicox 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> ); } } 90
  • 91. @drpicox 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> ); } } 91
  • 92. @drpicox 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> ); } } 92
  • 93. @drpicox 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> ); } } 93
  • 94. @drpicox 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} /> ... } } 94
  • 95. @drpicox Coordinator Outputs function convertIf(test, temperature, convert) { if (test) { return tryConvert(temperature, convert); } return temperature; } 95
  • 98. @drpicox Java 1.0 98 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(...)
  • 99. @drpicox Java 1.1 99 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(...) *
  • 100. @drpicox Java 1.2 100 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
  • 102. @drpicox Children Composition <card> <h1>Welcome</h1> <p> Find here a complete list of all the things that you love. </p> </card> 102
  • 103. @drpicox Children Composition function Card(props) { return ( <div className="card"> {props.children} </div> ); } 103
  • 105. @drpicox Many Children Composition <div class="SplitPane"> <div class="SplitPane-left"> <Contacts /> </div> <div class="SplitPane-left"> <Chat /> </div> </div> 105
  • 106. @drpicox 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> ); } 106
  • 107. @drpicox Many Children Composition function App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); } 107
  • 108. @drpicox Specialization function Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> </FancyBorder> ); } 108
  • 109. @drpicox Specialization function WelcomeDialog(props) { return ( <Dialog title="Welcome" message="Thanks for visiting!" /> ); } 109
  • 110. High Order Components (I) https://facebook.github.io/react/docs/higher-order- components.html
  • 111. @drpicox 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(); } } 111
  • 112. @drpicox Like high order functions const safeConvert = (convert) => { return (temperature) => { ... } } const safeKelvinToCelsius = safeConvert(kelvinToCelsius); const celsius = safeKelvinToCelsius(kelvin); 112
  • 113. @drpicox 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> ); } } 113
  • 114. @drpicox 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> ); } } 114
  • 115. @drpicox 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> ); } } 115
  • 116. @drpicox 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> ); } } } 116
  • 117. @drpicox Using Generic Component const TemperatureInputCelsius = makeTemperatureInput( safeCelsiusToKelvin, safeKelvinToCelsius, 'Celsius' ); const TemperatureInputFahrenheit = makeTemperatureInput( safeFahrenheitToKelvin, safeKelvinToFahrenheit, 'Fahrenheit' ); const TemperatureInputKelvin = makeTemperatureInput( identity, identity, 'Kelvin' ); 117
  • 118. @drpicox 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' ); 118
  • 119. @drpicox 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> ); } } 119
  • 120. @drpicox 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> ); } } } 120
  • 121. @drpicox High Order Component function makeThermostat(TemperatureInput) { return class extends React.Component { ... } } const ThermostatCelsius = makeThermostat(TemperatureInputCelsius); const ThermostatFahrenheit = makeThermostat(TemperatureInputFahrenheit); const ThermostatKelvin = makeThermostat(TemperatureInputKelvin); 121
  • 122. @drpicox Debug: displayName function makeTemperatureInpu( toKelvin, toFahrenheit, scaleName ) { class TemperatureInput extends React.Component { ... } TemperatureInput.displayName = `TemperatureInput(${scaleName})`; return TemperatureInput; } 122
  • 123. @drpicox Debug: displayName function makeThermostat(TemperatureInput) { class Thermostat extends React.Component { ... } Thermostat.displayName = `Thermostat(${getDisplayName(TemperatureInput)})`; return Thermostat; } 123
  • 124. @drpicox Warning // DON'T use HOCs in render functions! function App() { const TemperatureInputAbc = makeTemperatureInput(a, b, c); return <TemperatureInputAbc />; } class App extends React.Component { render() { const TemperatureInputAbc = makeTemperatureInput(a, b, c); return <TemperatureInputAbc />; } } 124
  • 125. @drpicox 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 125
  • 127. @drpicox Convention • Types of components • Routers • Containers • Presentational 127
  • 128. @drpicox Routes • Routers • Decides which component to render • Create components dynamically • Usually provided by library 128
  • 129. @drpicox 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 129
  • 130. @drpicox 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 130
  • 131. @drpicox 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> ); } } 131 Presentational Container
  • 132. @drpicox 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> ); } } 132 Presentational Container
  • 133. @drpicox Presentational Refactor function Clock { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); } 133
  • 134. @drpicox 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} />; } } 134