41
1 / 41 Intro & Concept Learning React Eueung Mulyana https://eueung.github.io/112016/react CodeLabs | Attribution-ShareAlike CC BY-SA

learning react

Embed Size (px)

Citation preview

1 / 41

Intro & Concept

Learning ReactEueung Mulyana

https://eueung.github.io/112016/reactCodeLabs | Attribution-ShareAlike CC BY-SA

Outline

Introduction

React Basics

Thinking in React

Examples

2 / 41

IntroductionA JavaScript library for building UIs | React

3 / 41

React - What? Why?

React is a declarative, e�cient, and �exible JavaScriptlibrary for building user interfaces.

4 / 41

React is a JavaScript library for creating user interfaces by Facebook and Instagram.Many people choose to think of React as the V in MVC.

"We built React to solve one problem: building large applications with data thatchanges over time."

React is simple: simply express how your app should look at any given point in time,and React will automatically manage all UI updates when your underlying data

changes.

React is declarative: when the data changes, React conceptually hits the "refresh"button, and knows to only update the changed parts. You don't need to care how

those changes are made.

React is all about building reusable components i.e. with React the only thing you dois build components. Components are so encapsulated, thus making code reuse,

testing, and separation of concerns easy.

How does It Work?

1. Maintains a "Virtual DOM"2. On changes, it creates a di�3. Applies the changes in batches to the DOM

Virtual DOM

Abstracts the DOM and give a simplerprogramming model and better performanceMinimizes the repaints focusing only on what haschanged

Data Flow

One-way reactive data �owMuch simpler then traditional data bindingDeclarative

Refs: React Investigation, React Native

5 / 41

Just the V in MVCReact does one thing very well, it manages updating the state of the view. Because you

can just use this, it is Relatively easy to integrate into other frameworks. Basically,React doesn't care about how your application is architectured.

PopularitySupport from some of the largest companies in the valley and a thriving open-source

community. Support continues to grow for it every day.

Server-Side RenderingSince react is able to represent the DOM virtually, it is able to render app state server

side and be able to then take the current UI state and manage it as a SPA after theclient has loaded. This allows for better SEO, performance and progressive

enhancement.

Devs ProductivityBecause of the large amount of tooling that supports react, and the focus on simplicity

in build react components, it can make building large applications much easier fordevelopers.

6 / 41

DeclarativeReact makes it painless to create interactive UIs. Design simple views for each state in

your application, and React will e�ciently update and render just the rightcomponents when your data changes. Declarative views make your code more

predictable, simpler to understand, and easier to debug.

Component-BasedBuild encapsulated components that manage their own state, then compose them to

make complex UIs. Since component logic is written in JavaScript instead of templates,you can easily pass rich data through your app and keep state out of the DOM.

Learn Once, Write AnywhereWe don't make assumptions about the rest of your technology stack, so you can

develop new features in React without rewriting existing code. React can also renderon the server using Node and power mobile apps using React Native.

Ref: facebook/react

7 / 41

Adding React to an Existing ApplicationYou don't need to rewrite your app to start using React.

We recommend adding React to a small part of your application, such an individualwidget, so you can see if it works well for your use case.

While React can be used without a build pipeline, we recommend setting it up so youcan be more productive. A modern build pipeline typically consists of:

A package manager, such as Yarn or npm. It lets you take advantage of a vastecosystem of third-party packages, and easily install or update them.A bundler, such as webpack or Browserify. It lets you write modular code andbundle it together into small packages to optimize load time.A compiler such as Babel. It lets you write modern JavaScript code that still works inolder browsers.

Ref: Installation - React

React Basics

8 / 41

Transformed @BrowserLoad React from a CDN

<script src="https://unpkg.com/react@15/dist/react.min.js"></script><script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script><script src="https://unpkg.com/[email protected]/babel.min.js"></script>

9 / 41

Using ReactVanilla JS

JSX (+ES2015)

Transformed @Browser

Precompiled (& bundled)

JSX lets you create JavaScript objects using XML/HTML syntax. To generate a link in Reactusing pure JavaScript you'd write:

React.createElement('a', {href: 'http://facebook.github.io/react/'}, 'Hello!')

With JSX this becomes:

<a href="http://facebook.github.io/react/">Hello!</a>

We've found this has made building React apps easier and designers tend to prefer thesyntax, but everyone has their own work�ow, so JSX is not required to use React.

10 / 41

JSXJSX is a syntax extension to JavaScript. We can use itwith React to describe what the UI should look like.

JSX may remind us of a template language, but itcomes with the full power of JavaScript. JSX produces

React "elements" (tree nodes).

JSX is not required to use React, but it makes codemore readable, and writing it feels like writing HTML.A simple transform is included with React that allows

converting JSX into native JavaScript for browsers todigest.

Ref: Introducing JSX - React

<!DOCTYPE html><html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="https://unpkg.com/react@latest/dist/react.js"></script> <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script> <script src="https://unpkg.com/[email protected]/babel.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel"> ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example') ); </script> </body></html>

Transformed @Browser

11 / 41

<!DOCTYPE html><html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="https://unpkg.com/react@latest/dist/react.js"></script> <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script> <script src="https://unpkg.com/[email protected]/babel.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel" src="src/hello.js"></script> </body></html>

ReactDOM.render( <h1>Hello, world!</h1>, document.getElementById('example'));

Transformed @Browser

12 / 41

Precompile JSX to JSnpm install -g babel-cli npm install -g babel-preset-react npm install -g babel-preset-es2015

$> babel --presets react hello.js --out-dir=../buildhello.js -> ..\build\hello.js

13 / 41

<!DOCTYPE html><html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="https://unpkg.com/react@latest/dist/react.js"></script> <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script> </head> <body> <div id="example"></div> <script src="build/hello.js"></script> </body></html>

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

# build/hello.js (compiled)ReactDOM.render(React.createElement( 'h1', null, 'Hello, world!'), document.getElementById('example'));

Precompiled

14 / 41

this.props 

<!DOCTYPE html><html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="https://unpkg.com/react@latest/dist/react.js"></script> <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script> <script src="https://unpkg.com/[email protected]/babel.min.js"></script> </head> <body> <div id="example"></div> <script type="text/babel" src="src/hello-props.js"></script> </body></html>

var HelloMessage = React.createClass({ render: function() { return <div>Hello {this.props.name}</div>; }});

ReactDOM.render(<HelloMessage name="John" />, document.getElementById('example'));

hello-props.js

15 / 41

this.state 

var Timer = React.createClass({ getInitialState: function() { return {secondsElapsed: 0}; }, tick: function() { this.setState({secondsElapsed: this.state.secondsElapsed + 1}); }, componentDidMount: function() { this.interval = setInterval(this.tick, 1000); }, componentWillUnmount: function() { clearInterval(this.interval); }, render: function() { return ( <div>Seconds Elapsed: {this.state.secondsElapsed}</div> ); }});

ReactDOM.render(<Timer />, document.getElementById('example'));

hello-state.js

16 / 41

Thinking in React

17 / 41

Thinking in ReactOne of the many great parts of React ishow it makes you think about apps as

you build them.

In this part, we will walk you through the thoughtprocess of building a searchable product data table

using React.

Ref: Thinking in React

1. Start with a Mock2. Break the UI into a Component Hierarchy3. Build a Static Version in React4. Identify the minimal representation of UI State5. Identify where the state should live6. Add inverse data �ow

18 / 41

Step #1

Data

[ { category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football" }, {category: "Sporting Goods", price: "$9.99", stocked: true, name: {category: "Sporting Goods", price: "$29.99", stocked: false, name: {category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch" {category: "Electronics", price: "$399.99", stocked: false, name: {category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7"];

19 / 41

Step #2

20 / 41

Step #3var PRODUCTS = [ {category: 'Sporting Goods', price: '$49.99', stocked: true, name: {category: 'Sporting Goods', price: '$9.99', stocked: true, name: {category: 'Sporting Goods', price: '$29.99', stocked: false, name: {category: 'Electronics', price: '$99.99', stocked: true, name: 'iPod Touch' {category: 'Electronics', price: '$399.99', stocked: false, name: {category: 'Electronics', price: '$199.99', stocked: true, name: 'Nexus 7'];

class ProductCategoryRow extends React.Component { render() { return <tr><th colSpan="2">{this.props.category}</th></tr>; }}

class ProductRow extends React.Component { render() { var name = this.props.product.stocked ? this.props.product.name : <span style={{color: 'red'}}> {this.props.product.name} </span>; return ( <tr> <td>{name}</td> <td>{this.props.product.price}</td> </tr> ); }}

21 / 41

Step #3class ProductTable extends React.Component { render() { var rows = []; var lastCategory = null; this.props.products.forEach(function(product) { if (product.category !== lastCategory) { rows.push(<ProductCategoryRow category={product.category} key={product.category} />); } rows.push(<ProductRow product={product} key={product.name} />); lastCategory = product.category; }); return ( <table> <thead> <tr> <th>Name</th> <th>Price</th> </tr> </thead> <tbody>{rows}</tbody> </table> ); }}

class SearchBar extends React.Component { render() { return ( <form> <input type="text" placeholder="Search..." /> <p> <input type="checkbox" /> {' '} Only show products in stock </p> </form> ); }}

class FilterableProductTable extends React.Component { render() { return ( <div> <SearchBar /> <ProductTable products={this.props.products} /> </div> ); }}

ReactDOM.render( <FilterableProductTable products={PRODUCTS} />, document.getElementById('container'));

22 / 41

Step #3Static Version: a version that takes your data model and renders the UIbut has no interactivity. It's best to decouple these processes becausebuilding a static version requires a lot of typing and no thinking, andadding interactivity requires a lot of thinking and not a lot of typing.

Here we want to build components that reuse other components andpass data using props. props are a way of passing data from parent tochild.

If you're familiar with the concept of state, don't use state at all to buildthis static version. State is reserved only for interactivity, that is, data thatchanges over time.

Passing props

<FilterableProductTable products={PRODUCTS} />

<SearchBar /><ProductTable products={this.props.products} />

<ProductCategoryRow category={product.category} key={product.category}<ProductRow product={product} key={product.name} />

23 / 41

Step #4To make your UI interactive, you need to be able to trigger changes toyour underlying data model. React makes this easy with state.

To build your app correctly, you �rst need to think of the minimal set ofmutable state that your app needs.

DRY (Don't Repeat Yourself): Figure out the absolute minimalrepresentation of the state your application needs and computeeverything else you need on-demand.

The original list of products is passed in as props, so that's not state. Thesearch text and the checkbox seem to be state since they change overtime and can't be computed from anything. And �nally, the �ltered list ofproducts isn't state because it can be computed by combining theoriginal list of products with the search text and value of the checkbox.

Think of all of the pieces of data in our example application. We have:

The original list of productsThe search text the user has enteredThe value of the checkboxThe �ltered list of products

Then, simply ask three questions about each piece of data:

Is it passed in from a parent via props? If so, it probably isn't state.Does it remain unchanged over time? If so, it probably isn't state.Can you compute it based on any other state or props in yourcomponent? If so, it isn't state.

24 / 41

Step #5Next, we need to identify which component mutates, or owns, this state.

Remember: React is all about one-way data �ow down the component hierarchy. It maynot be immediately clear which component should own what state. This is often the mostchallenging part for newcomers to understand.

For each piece of state in your application:

Identify every component that renders something based on that state.Find a common owner component (a single component above all the componentsthat need the state in the hierarchy).Either the common owner or another component higher up in the hierarchyshould own the state.If you can't �nd a component where it makes sense to own the state, create a newcomponent simply for holding the state and add it somewhere in the hierarchyabove the common owner component.

Identify Where Your State ShouldLive

ProductTable needs to �lter the product list basedon state and SearchBar needs to display the searchtext and checked state.The common owner component isFilterableProductTable.It conceptually makes sense for the �lter text andchecked value to live in FilterableProductTable

25 / 41

Step #5class FilterableProductTable extends React.Component { constructor(props) { super(props); this.state = { filterText: '', inStockOnly: false }; }

render() { return ( <div> <SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} /> <ProductTable products={this.props.products} filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} /> </div> ); }}

class SearchBar extends React.Component { render() { return ( <form> <input type="text" placeholder="Search..." value={this.props.filterText} /> <p> <input type="checkbox" checked={this.props.inStockOnly} /> {' '} Only show products in stock </p> </form> ); }}

26 / 41

Step #5For each product in products:

if no �lter-text matches, always return emptyif there is a match, checkbox is checked ANDstocked is false, return emptyotherwise return element

class ProductTable extends React.Component { render() { var rows = []; var lastCategory = null; this.props.products.forEach((product) => { if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && return; } if (product.category !== lastCategory) { rows.push(<ProductCategoryRow category={product.category} key={product.category} />); } rows.push(<ProductRow product={product} key={product.name} />); lastCategory = product.category; }); return ( <table> <thead> <tr> <th>Name</th> <th>Price</th> </tr> </thead> <tbody>{rows}</tbody> </table> ); }}

27 / 41

Step #6If you try to type or check the box in the prev. version of the example,you'll see that React ignores your input. This is intentional, as we've setthe value prop of the input to always be equal to the state passed in fromFilterableProductTable.

It renders correctly as a function of props and state �owing down thehierarchy. Now it's time to support data �owing the other way: the formcomponents deep in the hierarchy need to update the state inFilterableProductTable.

We want to make sure that whenever the user changes the form, weupdate the state to re�ect the user input:

Since components should only update their own state,FilterableProductTable will pass a callback to SearchBar that will�re whenever the state should be updated.We can use the onChange event on the inputs to be noti�ed of it.And the callback passed by FilterableProductTable will callsetState(), and the app will be updated.

class FilterableProductTable extends React.Component { constructor(props) { super(props); this.state = { filterText: '', inStockOnly: false }; this.handleUserInput = this.handleUserInput.bind(this); }

handleUserInput(filterText, inStockOnly) { this.setState({ filterText: filterText, inStockOnly: inStockOnly }); }

render() { return ( <div> <SearchBar filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} onUserInput={this.handleUserInput} /> <ProductTable products={this.props.products} filterText={this.state.filterText} inStockOnly={this.state.inStockOnly} /> </div> ); }}

28 / 41

Step #6class SearchBar extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); }

handleChange() { this.props.onUserInput( this.filterTextInput.value, this.inStockOnlyInput.checked ); }

#... render() { return ( <form> <input type="text" placeholder="Search..." value={this.props.filterText} ref={(input) => this.filterTextInput = input} onChange={this.handleChange} /> <p> <input type="checkbox" checked={this.props.inStockOnly} ref={(input) => this.inStockOnlyInput = input} onChange={this.handleChange} /> {' '} Only show products in stock </p> </form> ); }}

29 / 41

NotesIn the typical React data�ow, props are the only way that parent

components interact with their children. To modify a child, you re-render it with new props.

However, there are a few cases where you need to imperativelymodify a child outside of the typical data�ow. The child to be

modi�ed could be an instance of a React component, or it could be aDOM element. For both of these cases, React provides an escape

hatch.

React supports a special attribute that you can attach to anycomponent. The ref attribute takes a callback function, and the

callback will be executed immediately after the component ismounted or unmounted.

When the ref attribute is used on an HTML element, the ref callbackreceives the underlying DOM element as its argument. In the previous

code, the ref callback is used to store a reference to a DOM node.

See: Refs and the DOM

30 / 41

props, state & callback

Final Data Flow

31 / 41

Examples

32 / 41

TodoAppThis example uses state to track the current list of

items as well as the text that the user has entered.

See: React Mainpage

33 / 41

class TodoList extends React.Component { render() { return ( <ul> {this.props.items.map(item => ( <li key={item.id}>{item.text}</li> ))} </ul> ); }}

ReactDOM.render(<TodoApp />, document.getElementById('example'));

class TodoApp extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.state = {items: [], text: ''}; }

#...

#... render() { return ( <div> <h3>TODO</h3> <TodoList items={this.state.items} /> <form onSubmit={this.handleSubmit}> <input onChange={this.handleChange} value={this.state.text} /> <button>{'Add #' + (this.state.items.length + 1)}</button> </form> </div> ); }

handleChange(e) { this.setState({text: e.target.value}); }

handleSubmit(e) { e.preventDefault(); var newItem = { text: this.state.text, id: Date.now() }; this.setState((prevState) => ({ items: prevState.items.concat(newItem), text: '' })); }}

34 / 41

TodoApp

35 / 41

Notes

Default Behaviour To prevent default behavior in React, you must call preventDefaultexplicitly (e.preventDefault() - e is a synthetic event, compatible with the W3C)

State Updates May Be Asynchronous React may batch multiple setState() calls intoa single update for performance. Because this.props and this.state may be updatedasynchronously, you should not rely on their values for calculating the next state.

// Wrongthis.setState({ counter: this.state.counter + this.props.increment,});

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

The second form of setState() accepts the previous state as the �rst argument, andthe props at the time the update is applied as the second argument.

36 / 41

<!DOCTYPE html><html> <head> <meta charset="UTF-8" /> <title>Hello React!</title> <script src="https://unpkg.com/react@latest/dist/react.js"></script <script src="https://unpkg.com/react-dom@latest/dist/react-dom.js" <script src="https://unpkg.com/[email protected]/babel.min.js"

<script src="https://facebook.github.io/react/js/remarkable.min.js" </head> <body> <div id="example"></div> <script type="text/babel" src="src/app.js"></script> </body></html>

app.html

MarkdownEditorA Component Using External Plugins 

37 / 41

MardownEditorSingle Component

class MarkdownEditor extends React.Component { constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); this.state = {value: 'Type some *markdown* here!'}; }

handleChange() { this.setState({value: this.refs.textarea.value}); }

#...

getRawMarkup() { var md = new Remarkable(); return { __html: md.render(this.state.value) }; }

render() { return ( <div className="MarkdownEditor"> <h3>Input</h3> <textarea onChange={this.handleChange} ref="textarea" defaultValue={this.state.value} /> <h3>Output</h3> <div className="content" dangerouslySetInnerHTML={this.getRawMarkup()} /> </div> ); }}

ReactDOM.render(<MarkdownEditor />, document.getElementById('example'));

38 / 41

Refs

39 / 41

Refs1. A JavaScript library for building user interfaces | React2. facebook/react: A declarative, e�cient, and �exible JavaScript library for building user

interfaces.3. Getting Started | React4. Thinking in React5. React Investigation6. React Native7. Why React? | React Prev. Version

40 / 41

41 / 41

ENDEueung Mulyana

https://eueung.github.io/112016/reactCodeLabs | Attribution-ShareAlike CC BY-SA