React Component
Architecture
Objectives
-
Pass state to child components as props
-
Define which components own state
-
Use stateless functional components
How Is State Shared?
-
State is always passed from a parent down to a child component as a prop
-
State should not be passed to a sibling or a parent
Who owns the state?
class App extends Component {
render() {
return (
<div>
<Navbar />
<TicTacToe />
</div>
);
}
}
Owns the state
Wants State
State Should Be Owned by 1 Component
class InstructorItem extends Component {
constructor(props) {
super(props);
this.state = {
name: this.props.name,
hobbies: this.props.hobbies
};
}
render() {
return (
<div>
<h3>{this.state.name}</h3>
<h4>
Hobbies: {this.state.hobbies.join(", ")}
</h4>
</div>
);
}
}
Bad Practice: Don't Do This
Stateless Functional Components
Components implemented using a function,
not a class
The function implements the render method only:
no constructor, no state
import React from 'react';
const Greeting = props => (
<h1>Hello, {props.name}</h1>
);
export default Greeting;
Stateless Functional Component
Thinking In React
setState
Can Be Tricky
Objectives
-
Use a function as the first parameter to setState
-
Add a callback to setState to determine when the state is up to date
setState That Depends on Previous State
this.state = { counter: 1 };
this.setState({
counter: this.state.counter + 1
});
this.setState({
counter: this.state.counter + 1
});
Object.assign({},
{counter: this.state.counter + 1},
{counter: this.state.counter + 1},
{counter: this.state.counter + 1},
);
this.setState({
counter: this.state.counter + 1
});
setState is Asychronous
this.setState((prevState, props) => {
return {
counter: prevState.counter + 1
};
});
Solution: Update Function
Rule: When a setState depends on previous
state, use a function parameter
this.setState({name: "Tim"});
// Won't be updated yet
console.log(this.state.name);
setState is Asynchronous
this.setState({name: "Tim"}, () => {
console.log(
"Now state is up to date",
this.state.name
);
});
React
DevTools
Colored
Boxes
Virtual
DOM
Objectives
-
Describe the virtual DOM
-
Define a synthetic events
-
Describe changes in React 16 (Fiber)
Virtual DOM
A data structure stored by React that tracks changes from one render state to the next
If something has changed from one render to the next, the browser's DOM is update (Reconciliation)
Reconciliation
App
Instructor
Instructor
Instructor
App
Instructor
Instructor
Synthetic Events
Supports all the native browser events, but provides a consistent API on all browsers
React 16
What's New In Fiber?
React 16
render() {
return [
<div key='a'>First Element</div>,
<div key='b'>Second Element</div>
];
}
Render can return an array of JSX elements or a string
React 16
Error Boundary
React 16
Fiber
Events
Objectives
-
Demonstrate an onClick event
-
Using bond functions vs inline callbacks
onClick
class ClickExample extends Component {
constructor(props) {
super(props);
this.state = { name: "tim" };
}
render() {
return (
<div>
<p>{this.state.name}</p>
<button type="button"
onClick={() => this.setState({name: "TIM"})}>
UPPERCASE
</button>
</div>
);
}
}
class ClickExample extends Component {
constructor(props) {
super(props);
this.state = { name: "tim" };
this.handleClick = this.handleClick.bind(this);
}
handleClick(e) {
this.setState((prevState, props) => ({
name: prevState.name.toUpperCase()
});
}
render() {
return (
<div>
<p>{this.state.name}</p>
<button type="button" onClick={this.handleClick}>
UPPERCASE
</button>
</div>
);
}
}
render() {
return (
<div>
<p>{this.state.name}</p>
<button type="button" onClick={this.handleClick()}>
UPPERCASE
</button>
</div>
);
}
Common Mistake
The function will be invoked immediatley, not on the event
In Line Arrow Functions vs Bind
No noticeable performance benefits of using bind in the constructor
Forms
Objectives
-
Describe a controlled component vs uncontrolled
-
Handle a submit using onSubmit
Uncontrolled Component
<input type="text" />
React is not aware of what the user is typing, the browser is in charge of the state
Controlled Component
<input type="text" value={this.state.inputText}/>
React is now in control of the state via this.state.inputText, but the input can't be updated
Controlled Component With Update
<input
type="text"
name="inputText"
value={this.state.inputText}
onChange={(e) => {
this.setState({inputText: e.target.value})
}}
/>
React is now in control of the state via this.state.inputText and the state can change via onChange
onSubmit
<form onSubmit={(e) => {
e.preventDefault();
const data = [...this.state.data,
this.state.inputText];
this.setState({data, inputText: ''});
}}>
<input
type="text"
name="inputText"
value={this.state.inputText}
onChange={(e) => {
this.setState({[e.target.name]: e.target.value})
}}
/>
</form>
Common Mistake
<form>
<input
type="text"
name="inputText"
value={this.state.inputText}
onChange={(e) => {
this.setState({[e.target.name]: e.target.value})
}}
/>
<button
onClick={ /* trying to handle submit here */ }
type="submit"
>
SAVE
</button>
</form>
A button's click is not the same as a submit, use onSubmit
refs
Objectives
-
Define a ref in react
-
Use a ref on an uncontrolled input component
refs
A direct reference to
a DOM element
Use Cases
From React Docs
-
Managing focus, text selection, or media playback
-
Triggering imperative animations
-
Integrating with third-party DOM libraries
Warning!
Do not use refs when the job can be done with React
You should not need direct DOM access for most tasks
ref Example
<form onSubmit={(e) => {
e.preventDefault();
// access to the form value:
console.log(this.inputText.value);
}}>
<input
type="text"
ref={(input) => this.inputText = input}
/>
</form>
Todo
Exercise
Todo
Exercise
Solution
Recipe App
With State
Your
Turn
Memory
Game
HINTS
const CardState = {
HIDING: 0,
SHOWING: 1,
MATCHING: 2
};
Card States
let cards = [
{id: 0, cardState: CardState.HIDING, backgroundColor: 'red'},
{id: 1, cardState: CardState.HIDING, backgroundColor: 'red'},
{id: 2, cardState: CardState.HIDING, backgroundColor: 'navy'},
{id: 3, cardState: CardState.HIDING, backgroundColor: 'navy'},
{id: 4, cardState: CardState.HIDING, backgroundColor: 'green'},
{id: 5, cardState: CardState.HIDING, backgroundColor: 'green'},
{id: 6, cardState: CardState.HIDING, backgroundColor: 'yellow'},
{id: 7, cardState: CardState.HIDING, backgroundColor: 'yellow'},
{id: 8, cardState: CardState.HIDING, backgroundColor: 'black'},
{id: 9, cardState: CardState.HIDING, backgroundColor: 'black'},
{id: 10, cardState: CardState.HIDING, backgroundColor: 'purple'},
{id: 11, cardState: CardState.HIDING, backgroundColor: 'purple'},
{id: 12, cardState: CardState.HIDING, backgroundColor: 'pink'},
{id: 13, cardState: CardState.HIDING, backgroundColor: 'pink'},
{id: 14, cardState: CardState.HIDING, backgroundColor: 'lightskyblue'},
{id: 15, cardState: CardState.HIDING, backgroundColor: 'lightskyblue'}
];
this.state = {cards: shuffle(cards)};
Memory Game State
Your
Turn
Component
Lifecycle
Objectives
-
Describe the component lifecycle methods
-
Describe use cases for lifecycle methods
Lifecycle Methods
Mounting
constructor()
componentWillMount()
render()
componentDidMount()
Lifecycle Methods
Unmounting
componentWillUnmount
Lifecycle Methods
Updating
componentWillReceiveProps(nextProps)
shouldComponentUpdate(nextProps, nextState)
componentWillUpdate(nextProps, nextState)
render()
componentDidUpdate(prevProps, prevState)
Forcing Update
Updating
forceUpdate(callback)
Skips shouldComponentUpdate and forces a render. Should be avoided in most cases.
Lifecycle Methods
Lifecycle Method Examples
componentWillUnmount
Example
const NUM_BOXES = 32;
class Boxes extends Component {
constructor(props) {
super(props);
const boxes = Array(NUM_BOXES).fill()
.map(this.getRandomColor, this);
this.state = {boxes};
this.intervalId = setInterval(() => {
const boxes = this.state.boxes.slice();
const ind = Math.floor(Math.random()*boxes.length);
boxes[ind] = this.getRandomColor();
this.setState({boxes});
}, 300);
}
componentWillUnmount() {
clearInterval(this.intervalId);
}
}
componentDidMount
AJAX Example
Hacker News API
GET https://hacker-news.firebaseio.com/v0/topstories.json
[15300069,15298833,...15267532]
GET https://hacker-news.firebaseio.com/v0/item/15300069.json
{"by":"maguay", "id":15300069, "title":"Google signs agreement with HTC", "url":"https://www.blog.google/topics/hardware/google-signs-agreement-htc-continuing-our-big-bet-hardware/" }
Your
Turn
Flag
App
REST Countries API
[ ...,
{"name":"United States of America",
"population":323947000, "latlng":[38.0,-97.0],
"flag":"https://restcountries.eu/data/usa.svg"},
{"name":"Mexico",
"population":122273473,"latlng":[23.0,-102.0],
"flag":"https://restcountries.eu/data/mex.svg"},
...
]
GET https://restcountries.eu/rest/v2/all
Flag
App
Solution
React Slides lots of stuff about state
By Elie Schoppik
React Slides lots of stuff about state
- 1,848