basic tutorial of react for programmers

134
Basic ReactJS for Programmers by Dr. David Rodenas

Upload: david-rodenas

Post on 11-Apr-2017

24 views

Category:

Software


1 download

TRANSCRIPT

Page 1: Basic Tutorial of React for Programmers

Basic ReactJS for Programmers

by Dr. David Rodenas

Page 2: Basic Tutorial of React for Programmers

Origin

Page 3: Basic Tutorial of React for Programmers

@drpicox

FB about MVC

3

https://youtu.be/nYkdrAPrdcw?t=10m20s

2014

Page 4: Basic Tutorial of React for Programmers

@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.”

Page 5: Basic Tutorial of React for Programmers

@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.”

Page 6: Basic Tutorial of React for Programmers

@drpicox

FB about MVC

6

f lux

Page 7: Basic Tutorial of React for Programmers

@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.”

Page 8: Basic Tutorial of React for Programmers

ReactJS

Page 9: Basic Tutorial of React for Programmers

@drpicox

Prerequisite

Make an account in codepen.io

Page 11: Basic Tutorial of React for Programmers

Basics

Page 12: Basic Tutorial of React for Programmers

@drpicox

Hello World<!-- hello-world.html --> <div id="root"></div>

// hello-world.js ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('root') );

12https://facebook.github.io/react/docs/hello-world.html

Page 13: Basic Tutorial of React for Programmers

@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'));

13https://babeljs.io/repl

Page 14: Basic Tutorial of React for Programmers

@drpicox

Do not fear change• ReactJS only updates what changes

• Although everything is regenerated every time

• Open countdown example at codepen with chromehttp://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

Page 15: Basic Tutorial of React for Programmers

JSX

https://facebook.github.io/react/docs/introducing-jsx.html

Page 16: Basic Tutorial of React for Programmers

@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

Page 17: Basic Tutorial of React for Programmers

@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

Page 18: Basic Tutorial of React for Programmers

@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

Page 19: Basic Tutorial of React for Programmers

@drpicox

JSX// It can be multiline (be careful using return) const element = <h1> Hello, world! </h1>;

19

Page 20: Basic Tutorial of React for Programmers

@drpicox

JSX// It can be multiline (better) const element = <h1> Hello, world! </h1>;

20

Page 21: Basic Tutorial of React for Programmers

@drpicox

JSX// It can be multiline (recommended) const element = ( <h1> Hello, world! </h1> );

21

Page 22: Basic Tutorial of React for Programmers

@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

Page 23: Basic Tutorial of React for Programmers

@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

Page 24: Basic Tutorial of React for Programmers

@drpicox

JSX - Cross-site-scripting// It is just a string const title = response.veryMaliciousInput;

// This is save const element = <h1>{title}</h1>;

24

Page 25: Basic Tutorial of React for Programmers

@drpicox

JSX// Is XML-like const element = ( <div> Hello <br/> World </div> );

// Elements must be terminated const element = ( <div> Hello <br> World </div> );

25

Page 26: Basic Tutorial of React for Programmers

Rendering Elements

https://facebook.github.io/react/docs/rendering-elements.html

Page 27: Basic Tutorial of React for Programmers

@drpicox

Rendering Elements// JSX elements are just memory objects const element = <h1>Hello, world</h1>;

27

Page 28: Basic Tutorial of React for Programmers

@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

Page 29: Basic Tutorial of React for Programmers

@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

Page 30: Basic Tutorial of React for Programmers

Components and Props

https://facebook.github.io/react/docs/components-and-props.html

Page 31: Basic Tutorial of React for Programmers

@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

Page 32: Basic Tutorial of React for Programmers

@drpicox

Render a Componentconst element = <Welcome name="Dave" />;

32

Page 33: Basic Tutorial of React for Programmers

@drpicox

Composing Componentsfunction App() { return ( <div> <Welcome name="Alice" /> <Welcome name="Bob" /> <Welcome name="Dave" /> </div> ); }

33

Page 34: Basic Tutorial of React for Programmers

@drpicox

Refactoring Componentsfunction 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

Page 35: Basic Tutorial of React for Programmers

@drpicox

Refactoring Componentsfunction 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} />

Page 36: Basic Tutorial of React for Programmers

@drpicox

Refactoring Componentsfunction 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

Page 37: Basic Tutorial of React for Programmers

@drpicox

Refactoring Componentsfunction 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

Page 38: Basic Tutorial of React for Programmers

@drpicox

Refactoring Componentsfunction UserInfo(props) { return ( <div className="UserInfo"> <Avatar user={props.user} /> <div className="UserInfo-name"> {props.user.name} </div> </div> ); }

38

Page 39: Basic Tutorial of React for Programmers

@drpicox

Refactoring Componentsfunction 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

Page 40: Basic Tutorial of React for Programmers

@drpicox

Props are Read-Only// Render must be read-only function MissbehavingComponent(props) { return <h1>{props.n += 1}</h1>; }

40

Page 41: Basic Tutorial of React for Programmers

State and Lifecycle

https://facebook.github.io/react/docs/state-and-lifecycle.html

Page 42: Basic Tutorial of React for Programmers

@drpicox

Function to Class Componentfunction Clock(props) { return ( <div> <h1>Hello, world!</h1> <h2>It is {props.time}.</h2> </div> ); }

42

Page 43: Basic Tutorial of React for Programmers

@drpicox

Function to Class Componentclass Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); } }

43

Page 44: Basic Tutorial of React for Programmers

@drpicox

Function to Class Componentclass Clock extends React.Component { render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); } }

44

Page 45: Basic Tutorial of React for Programmers

@drpicox

Setup Stateclass Clock extends React.Component { constructor(props) { super(props); this.state = {time: Date.now()}; } render() { ... } }

45

Page 46: Basic Tutorial of React for Programmers

@drpicox

Setup Stateclass Clock extends React.Component { constructor(props) { ... } render() { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.state.time}.</h2> </div> ); } }

46

Page 47: Basic Tutorial of React for Programmers

@drpicox

Lifecycle Methodsclass Clock extends React.Component { constructor(props) { ... } componentDidMount() { /* TODO */ } componentWillUnmount() { /* TODO */ } render() { ... } }

47

Page 48: Basic Tutorial of React for Programmers

@drpicox

Lifecycle Methodsclass Clock extends React.Component { constructor(props) { ... } componentDidMount() { this.timerId = setInterval( () => this.setState({time: Date.now()}), 1000 ); } componentWillUnmount() { /* TODO */ } render() { ... } }

48

Page 49: Basic Tutorial of React for Programmers

@drpicox

Lifecycle Methodsclass Clock extends React.Component { constructor(props) { ... } componentDidMount() { ... } componentWillUnmount() { clearInterval(this.timerId); } render() { ... } }

49

Page 50: Basic Tutorial of React for Programmers

@drpicox

setState Asynchronous// Wrong! setState({counter: this.state.counter + 1});

// Correct setState((prevState, props) => ({ counter: prevState.counter + 1 });

50

Page 51: Basic Tutorial of React for Programmers

@drpicox

States are Mergedconstructor() { this.state = {posts: [], users: []}; }

componentDidMount() { getPosts((posts) => this.setState({posts})); getUsers((users) => this.setState({users})); }

51

Page 52: Basic Tutorial of React for Programmers

@drpicox

State Isolatedfunction App() { return ( <div> <Clock /> <Clock /> <Clock /> </div> ); }

52

Page 53: Basic Tutorial of React for Programmers

Handling Events

Page 54: Basic Tutorial of React for Programmers

@drpicox

onEvent={fn}function ButtonLogHello() { function handleClick() { console.log('The button is clicked'); }

return ( <button onClick={handleClick}> click me </button> ); }

54

Page 55: Basic Tutorial of React for Programmers

@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

Page 56: Basic Tutorial of React for Programmers

@drpicox

onEvent={fn}// It can inline functions (are expressions) function DivLogHello() { return ( <button onClick={() => console.log('oh')}> click me </button> ); }

56

Page 57: Basic Tutorial of React for Programmers

@drpicox

Toggle Exampleclass 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

Page 58: Basic Tutorial of React for Programmers

@drpicox

Toggle Exampleclass Toggle extends React.Component { constructor(props) { super(props); this.state = {isToggleOn: true}; } handleClick = () => { ... } ...

58

https://facebook.github.io/react/docs/handling-events.html

Page 59: Basic Tutorial of React for Programmers

Conditional Rendering

https://facebook.github.io/react/docs/conditional-rendering.html

Page 60: Basic Tutorial of React for Programmers

@drpicox

Conditional Renderingfunction UserGreeting(props) { return <h1>Welcome back!</h1>; }

function GuestGreeting(props) { return <h1>Please sign up.</h1>; }

60

Page 61: Basic Tutorial of React for Programmers

@drpicox

By returnfunction 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

Page 62: Basic Tutorial of React for Programmers

@drpicox

By variablerender() { 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

Page 63: Basic Tutorial of React for Programmers

@drpicox

By && expressionfunction Mailbox(props) { const unreadMessages = props.unreadMessages;

return ( <div> <h1>Hello!</h1> {unreadMessages.length > 0 && <h2> You have {unreadMessages.length} unread messages. </h2> } </div> ); }

63

Page 64: Basic Tutorial of React for Programmers

@drpicox

By ?: expressionrender() { const isLoggedIn = this.state.isLoggedIn; return ( <div> {isLoggedIn ? ( <LogoutButton onClick={this.handleLogoutClick} /> ) : ( <LoginButton onClick={this.handleLoginClick} /> )} </div> ); }

64

Page 65: Basic Tutorial of React for Programmers

@drpicox

Prevent Renderfunction WarningBanner(props) { if (!props.warn) { return null; }

return ( <div className="warning"> Warning! </div> ); }

65

Page 66: Basic Tutorial of React for Programmers

Lists and Keys

Page 67: Basic Tutorial of React for Programmers

@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

Page 68: Basic Tutorial of React for Programmers

@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

Page 69: Basic Tutorial of React for Programmers

@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

Page 70: Basic Tutorial of React for Programmers

@drpicox

Keyfunction NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); }

70

Page 71: Basic Tutorial of React for Programmers

@drpicox

Key - indexconst todoItems = todos.map((todo, index) => // Only do this if items have no stable IDs <li key={index}> {todo.text} </li> );

71

Page 72: Basic Tutorial of React for Programmers

@drpicox

Key - Refactor Componentfunction NumberList(props) { const numbers = props.numbers; const listItems = numbers.map((number) => <li key={number.toString()}> {number} </li> ); return ( <ul>{listItems}</ul> ); }

72

Page 73: Basic Tutorial of React for Programmers

@drpicox

Key - Refactor Componentfunction ListItem(props) { return ( // Wrong! should not be here <li key="props.number.toString()"> {props.number} </li> ); }

73

Page 74: Basic Tutorial of React for Programmers

@drpicox

Key - Refactor Componentfunction 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

Page 75: Basic Tutorial of React for Programmers

@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

Page 76: Basic Tutorial of React for Programmers

@drpicox

.map inside JSXfunction NumberList(props) { const numbers = props.numbers; return ( <ul> {numbers.map((number) => <ListItem key={number.toString()} value={number} /> )} </ul> ); }

76

Page 77: Basic Tutorial of React for Programmers

Forms

Page 78: Basic Tutorial of React for Programmers

@drpicox

Controlled Componentsclass 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

Page 79: Basic Tutorial of React for Programmers

@drpicox

Controlled Componentsclass NameForm extends React.Component { constructor(props) { super(props); this.state = {value: ''}; } handleChange = (event) => { ... } handleSubmit = (event) => { ... } render() { ... } }

79

Page 80: Basic Tutorial of React for Programmers

@drpicox

Controlled Componentsclass NameForm extends React.Component { constructor() { ... } handleChange = (event) => { this.setState({ value: event.target.value.toLowerCase() }); } handleSubmit = (event) => { ... } render() { ... } }

80

Page 81: Basic Tutorial of React for Programmers

@drpicox

Textarea<textarea value={this.state.value} onChange={this.handleChange} />

81

Page 82: Basic Tutorial of React for Programmers

@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

Page 83: Basic Tutorial of React for Programmers

@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

Page 84: Basic Tutorial of React for Programmers

@drpicox

Multiple InputshandleInputChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name;

this.setState({ [name]: value }); }

84

Page 85: Basic Tutorial of React for Programmers

Synchronized States

https://facebook.github.io/react/docs/lifting-state-up.html

Page 86: Basic Tutorial of React for Programmers

@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

Page 87: Basic Tutorial of React for Programmers

@drpicox

Synchronizing - Coordinatorclass 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

Page 88: Basic Tutorial of React for Programmers

@drpicox

Synchronizing - Producerclass 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

Page 89: Basic Tutorial of React for Programmers

@drpicox

Synchronizing - Producerclass 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

Page 90: Basic Tutorial of React for Programmers

@drpicox

Synchronizing - Producerclass 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

Page 91: Basic Tutorial of React for Programmers

@drpicox

Synchronizing - Producerclass 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

Page 92: Basic Tutorial of React for Programmers

@drpicox

Synchronizing - Coordinatorclass 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

Page 93: Basic Tutorial of React for Programmers

@drpicox

Coordinator - Inputsclass 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

Page 94: Basic Tutorial of React for Programmers

@drpicox

Coordinator Outputsclass 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

Page 95: Basic Tutorial of React for Programmers

@drpicox

Coordinator Outputsfunction convertIf(test, temperature, convert) { if (test) { return tryConvert(temperature, convert); } return temperature; }

95

Page 96: Basic Tutorial of React for Programmers

@drpicox

Exercise

96

https://codepen.io/drpicox/pen/ryrypJ

Exercise React Temperature

Page 97: Basic Tutorial of React for Programmers

Component Composition

https://facebook.github.io/react/docs/composition-vs-inheritance.html

Page 98: Basic Tutorial of React for Programmers

@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(...)

Page 99: Basic Tutorial of React for Programmers

@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(...)

*

Page 100: Basic Tutorial of React for Programmers

@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

Page 101: Basic Tutorial of React for Programmers

@drpicox

Children Composition

101

CardContents

Page 102: Basic Tutorial of React for Programmers

@drpicox

Children Composition<card> <h1>Welcome</h1> <p> Find here a complete list of all the things that you love. </p> </card>

102

Page 103: Basic Tutorial of React for Programmers

@drpicox

Children Compositionfunction Card(props) { return ( <div className="card"> {props.children} </div> ); }

103

Page 104: Basic Tutorial of React for Programmers

@drpicox

Many Children Composition

104

SplitPaneLeft Right

Page 105: Basic Tutorial of React for Programmers

@drpicox

Many Children Composition<div class="SplitPane"> <div class="SplitPane-left"> <Contacts /> </div> <div class="SplitPane-left"> <Chat /> </div> </div>

105

Page 106: Basic Tutorial of React for Programmers

@drpicox

Many Children Compositionfunction SplitPane(props) { return ( <div className="SplitPane"> <div className="SplitPane-left"> {props.left} </div> <div className="SplitPane-right"> {props.right} </div> </div> ); }

106

Page 107: Basic Tutorial of React for Programmers

@drpicox

Many Children Compositionfunction App() { return ( <SplitPane left={ <Contacts /> } right={ <Chat /> } /> ); }

107

Page 108: Basic Tutorial of React for Programmers

@drpicox

Specializationfunction Dialog(props) { return ( <FancyBorder color="blue"> <h1 className="Dialog-title"> {props.title} </h1> <p className="Dialog-message"> {props.message} </p> </FancyBorder> ); }

108

Page 109: Basic Tutorial of React for Programmers

@drpicox

Specializationfunction WelcomeDialog(props) { return ( <Dialog title="Welcome" message="Thanks for visiting!" /> ); }

109

Page 110: Basic Tutorial of React for Programmers

High Order Components (I)

https://facebook.github.io/react/docs/higher-order-components.html

Page 111: Basic Tutorial of React for Programmers

@drpicox

Like high order functionsconst 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

Page 112: Basic Tutorial of React for Programmers

@drpicox

Like high order functionsconst safeConvert = (convert) => { return (temperature) => { ... } }

const safeKelvinToCelsius = safeConvert(kelvinToCelsius);

const celsius = safeKelvinToCelsius(kelvin);

112

Page 113: Basic Tutorial of React for Programmers

@drpicox

Specific Componentclass 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

Page 114: Basic Tutorial of React for Programmers

@drpicox

Specific Componentclass 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

Page 115: Basic Tutorial of React for Programmers

@drpicox

Generic Componentclass 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

Page 116: Basic Tutorial of React for Programmers

@drpicox

Generic Componentfunction 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

Page 117: Basic Tutorial of React for Programmers

@drpicox

Using Generic Componentconst TemperatureInputCelsius = makeTemperatureInput( safeCelsiusToKelvin, safeKelvinToCelsius, 'Celsius' );

const TemperatureInputFahrenheit = makeTemperatureInput( safeFahrenheitToKelvin, safeKelvinToFahrenheit, 'Fahrenheit' );

const TemperatureInputKelvin = makeTemperatureInput( identity, identity, 'Kelvin' ); 117

Page 118: Basic Tutorial of React for Programmers

@drpicox

Using Generic Componentconst TemperatureInputCelsius = makeTemperatureInput( safeConvert(celsiusToKelvin), safeConvert(kelvinToCelsius), 'Celsius' );

const TemperatureInputFahrenheit = makeTemperatureInput( safeConvert(fahrenheitToKelvin), safeConvert(kelvinToFahrenheit), 'Fahrenheit' );

const TemperatureInputKelvin = makeTemperatureInput( (x) => x, (x) => x, 'Kelvin' ); 118

Page 119: Basic Tutorial of React for Programmers

@drpicox

High Order Componentclass 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

Page 120: Basic Tutorial of React for Programmers

@drpicox

High Order Componentfunction 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

Page 121: Basic Tutorial of React for Programmers

@drpicox

High Order Componentfunction makeThermostat(TemperatureInput) { return class extends React.Component { ... } }

const ThermostatCelsius = makeThermostat(TemperatureInputCelsius);

const ThermostatFahrenheit = makeThermostat(TemperatureInputFahrenheit);

const ThermostatKelvin = makeThermostat(TemperatureInputKelvin); 121

Page 122: Basic Tutorial of React for Programmers

@drpicox

Debug: displayNamefunction makeTemperatureInpu( toKelvin, toFahrenheit, scaleName ) { class TemperatureInput extends React.Component { ... } TemperatureInput.displayName = `TemperatureInput(${scaleName})`; return TemperatureInput; }

122

Page 123: Basic Tutorial of React for Programmers

@drpicox

Debug: displayNamefunction makeThermostat(TemperatureInput) { class Thermostat extends React.Component { ... } Thermostat.displayName = `Thermostat(${getDisplayName(TemperatureInput)})`; return Thermostat; }

123

Page 124: Basic Tutorial of React for Programmers

@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

Page 125: Basic Tutorial of React for Programmers

@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

Page 127: Basic Tutorial of React for Programmers

@drpicox

Convention• Types of components

• Routers

• Containers

• Presentational

127

Page 128: Basic Tutorial of React for Programmers

@drpicox

Routes• Routers

• Decides which component to render

• Create components dynamically

• Usually provided by library

128

Page 129: Basic Tutorial of React for Programmers

@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

Page 130: Basic Tutorial of React for Programmers

@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

Page 131: Basic Tutorial of React for Programmers

@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

Page 132: Basic Tutorial of React for Programmers

@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

Page 133: Basic Tutorial of React for Programmers

@drpicox

Presentational Refactorfunction Clock { return ( <div> <h1>Hello, world!</h1> <h2>It is {this.props.time}.</h2> </div> ); }

133

Page 134: Basic Tutorial of React for Programmers

@drpicox

Container Refactorclass 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