Build web apps with ReactJS
===
Lee @ DevC Taipei 讀書會 2019-07-21
https://hackmd.io/@SYkYaRqjTQm-oj2WqaWhUQ/ByhSB7AZB
---
## Handle events
---
```jsx=
class MyComponent extends React.Component {
handleClick(event) {
//...do something
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
```
---
```jsx=
class MyComponent extends React.Component {
handleClick(event) {
console.log(this); // undefined
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
```
ref: [This is why we need to bind event handlers in Class Components in React](https://www.freecodecamp.org/news/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb/)
----
### Call-site
```javascript=
function baz() {
console.log( "baz" );
bar(); // <-- call-site for `bar`
}
function bar() {
console.log( "bar" );
}
baz(); // <-- call-site for `baz`
```
ref: [this & object prototypes ch2](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md)
----
### Default Binding in strict mode
```javascript=
"use strict"
function foo() {
console.log( this.a );
}
var a = 2;
foo(); // TypeError: `this` is `undefined`
```
ref: [this & object prototypes ch2](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md)
----
### Implicit Binding
```javascript=
function foo() {
console.log( this.a );
}
var obj1 = { a: 2, foo: foo };
var obj2 = { a: 3, foo: foo };
obj1.foo(); // 2
obj2.foo(); // 3
```
ref: [this & object prototypes ch2](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md)
----
```javascript=
class Foo {
constructor(name) {
this.name = name
}
display() {
console.log(this.name);
}
}
const foo = new Foo('Saurabh');
const display = foo.display;
display(); // TypeError: this is undefined
```
ref: [This is why we need to bind event handlers in Class Components in React](https://www.freecodecamp.org/news/this-is-why-we-need-to-bind-event-handlers-in-class-components-in-react-f7ea1a6f93eb/)
---
### React Without JSX
```javascript=
class MyComponent extends React.Component {
handleClick(event) {
console.log(this); // undefined
}
render() {
return (
React.createElement(
'button',
{ onClick: this.handleClick },
'Click me'
)
);
}
}
```
ref: [React Without JSX](https://reactjs.org/docs/react-without-jsx.html)
---
### Solution
```jsx=
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
console.log(this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
```
----
#### Arrow function - Lexical this
```jsx=
class MyComponent extends React.Component {
handleClick(event) {
console.log(this);
}
render() {
return (
<button onClick={(e) => this.handleClick(e)}>
Click me
</button>
);
}
}
```
ref: [lexical-this](https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#lexical-this)
----
#### Public Class Fields Syntax - stage 3
```jsx=
class MyComponent extends React.Component {
handleClick = (event) => {
console.log(this);
}
render() {
return (
<button onClick={this.handleClick}>
Click me
</button>
);
}
}
```
ref: [proposal-class-fields](https://github.com/tc39/proposal-class-fields)
---
## Understand one-way data bindings
---
React apps are organized as a series of nested components. These components are functional in nature: that is, they receive information through arguments (represented in the props attribute) and pass information via their return values (the return value of the render function). This is called unidirectional data flow. Data is passed down from components to their children.
ref: [Understand one-way data bindings](https://openclassrooms.com/en/courses/4286486-build-web-apps-with-reactjs/4286721-understand-one-way-data-bindings)
---

----
```jsx
import React from 'react';
import ChangeColorButton from './ChangeColorButton.js';
class ColoredBlock extends React.Component {
constructor(props) {
super(props);
this.state = { color: 'red' };
}
render() {
return (
<div style={{
height: '200px', width: '200px',
backgroundColor: this.state.color
}}>
<ChangeColorButton currentColor={this.state.color} />
</div>
)
}
}
export default ColoredBlock;
```
----
```jsx
import React from 'react';
class ChangeColorButton extends React.Component {
render() {
return (
<button>
Change the color: {this.props.currentColor}
</button>
);
}
}
export default ChangeColorButton;
```
----
#### This is wrong!!!
```jsx
import React from 'react';
class ChangeColorButton extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.props.currentColor =
this.props.currentColor === 'red' ? 'blue' : 'red';
}
render() {
return (
<button onClick={this.handleClick}>
Change the color: {this.props.currentColor}
</button>
);
}
}
export default ChangeColorButton;
```
---
#### Understand one-way data bindings

----
#### Pass callback method
```jsx
import React from 'react';
import ChangeColorButton from './ChangeColorButton.js';
class ColoredBlock extends React.Component {
constructor(props) {
super(props);
this.state = { color: 'red' };
this.changeColor = this.changeColor.bind(this);
}
changeColor() {
let newColor =
this.state.color === 'red' ? 'blue' : 'red';
this.setState({ color: newColor });
}
render() {
return (
<div style={{
height: '200px', width: '200px',
backgroundColor: this.state.color
}}>
<ChangeColorButton
currentColor={this.state.color}
clickHandler={this.changeColor}
/>
</div>
)
}
}
export default ColoredBlock;
```
----
```jsx
import React from 'react';
class ChangeColorButton extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.props.clickHandler();
console.log('clicked');
}
render() {
return (
<button onClick={this.handleClick}>
Change the color: {this.props.currentColor}
</button>
);
}
}
export default ChangeColorButton;
```
----
```jsx
import React from 'react';
class ChangeColorButton extends React.Component {
render() {
return (
<button onClick={this.props.clickHandler}>
Change the color: {this.props.currentColor}
</button>
);
}
}
export default ChangeColorButton;
```
---
#### State updates may be asynchronous
```javascript
changeColor() {
let newColor =
this.state.color === 'red' ? 'blue' : 'red';
this.setState({ color: newColor });
}
```
```javascript
changeColor() {
this.setState((prevState, props) => ({
color: prevState.color === 'red' ? 'blue' : 'red'
}));
}
```
ref: [State updates may be asynchronous](https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous)
---
{"metaMigratedAt":"2023-06-14T22:55:26.338Z","metaMigratedFrom":"Content","title":"Build web apps with ReactJS","breaks":true,"contributors":"[{\"id\":\"49891869-1aa3-4d09-bea2-3d96a9a5a151\",\"add\":7952,\"del\":343}]"}