React Hook
In Deep
React Lifecycle
Redux Store
dispatch action
connect state
Redux Store
dispatch action
connect state
props / state lifecycle
Redux Store
dispatch action
connect state
props / state lifecycle
Entropy
Chaos
Function
Purely
Pure Function
Focus on
Input & Output
No timing-related state
variables you cared
(Reduce state machine in single component)
(useEffect / useCallback / useMemo)
(tick scoped state)
useState
import React, { useState } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
return (
<button
onClick={() => setCount(count + 1)}
type="button">
Click to add!
</button>
);
}
useEffect
import React, { useState, useEffect } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Click ${count} times`;
});
return (
<button
onClick={() => setCount(count + 1)}
type="button">
Click to add!
</button>
);
}
Execute order
1. execute component function to get render results
(with state from useState)
2. call useEffect function after result merge into react tree
(check watch variables value between each render)
JS Scope
import React, { useState, useEffect } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
console.log(`Clicked ${count} 2 seconds ago`);
}, 2000);
});
return (
<button
onClick={() => setCount(count + 1)}
type="button">
Click to add!
</button>
);
}
One time task
import React, { useState, useEffect } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
useEffect(() => {
setTimeout(() => {
console.log(`Clicked ${count} 2 seconds ago`);
}, 2000);
}, [count]);
useEffect(() => {
const intvalId = setInterval(() => {
console.log('Time is passing...');
}, 1000);
return () => clearInterval(intvalId);
}, []);
return (
<button
onClick={() => setCount(count + 1)}
type="button">
Click to add!
</button>
);
}
Honest always
import React, { useState, useEffect } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
useEffect(() => {
const intvalId = setInterval(() => {
console.log('Time is passing...');
setCount(count + 1);
}, 1000);
return () => clearInterval(intvalId);
}, [count]);
return (
<button
onClick={() => setCount(count + 1)}
type="button">
Click to add!
</button>
);
}
Self Update
import React, { useState, useEffect } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
useEffect(() => {
const intvalId = setInterval(() => {
console.log('Time is passing...');
setCount(c => c + 1);
}, 1000);
return () => clearInterval(intvalId);
}, []);
return (
<button
onClick={() => setCount(count + 1)}
type="button">
Click to add!
</button>
);
}
Mixin
import React, { useState, useEffect } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
const [step, setStep] = useState(1);
useEffect(() => {
const intvalId = setInterval(() => {
console.log('Time is passing...');
setCount(c => c + step);
}, 1000);
return () => clearInterval(intvalId);
}, [step]);
return (
<div>
<span>{count}</span>
<input
type="text"
value={step}
onChange={e => setStep(Number(e.target.value){ />
</div>
);
}
useCallback
import React, { useState, useEffect, useCallback } from 'react';
function ComponentIsMe() {
const [term, setTerm] = useState('');
const getSearchURL = useCallback(() => `http://aa.com/search?term=${term}`, [term]);
useEffect(() => {
const data = fetch(getSearchURL());
}, [getSearchURL]);
// ... render
}
props ready
import React, { useState, useEffect, useCallback } from 'react';
function Parent() {
const [term, setTerm] = useState('');
const fetchData = useCallback(() => `http://aa.com/search?term=${term}`, [term]);
return (
<Child fetchData={fetchData} />
);
}
function Child({ fetchData }) {
const [data, setData] = useState(null);
useEffect(async () => {
const response = await fetchData();
setData(response);
}, [fetchData]);
}
Race condition
In class component
import React, { PureComponent } from 'react';
class Article extends PureComponent {
state = {
article: null
};
componentDidMount() {
this.fetchData(this.props.id);
}
componentDidUpdate(prevProps) {
if (prevProps.id !== this.props.id) {
this.fetchData(this.props.id);
}
}
async fetchData(id) {
const article = await API.fetchArticle(id);
this.setState({ article });
}
// ...
}
Race Condition
Select Article Id = 1
Call API with ID = 1
Select Article Id = 2
Call API with ID = 2
API Res. ID = 1
API Res. ID = 2
select 2 but data is 1
In Hook
import React, { useState, useEffect } from 'react';
function Article({ id }) {
const [article, setArticle] = useState(null);
useEffect(() => {
let cancelled = false;
async function fetchArticle() {
const response = await fetchArticleFromId(id);
if (!cancelled) {
setArticle(response);
}
}
fetchArticle();
return () => {
cancelled = true;
};
}, [id]);
// render ...
}
React Fiber
By Chia Yu Pai
React Fiber
- 426