In Deep
Redux Store
dispatch action
connect state
Redux Store
dispatch action
connect state
props / state lifecycle
Redux Store
dispatch action
connect state
props / state lifecycle
Purely
Input & Output
No timing-related state
variables you cared
(Reduce state machine in single component)
(useEffect / useCallback / useMemo)
(tick scoped state)
import React, { useState } from 'react';
function ComponentIsMe() {
const [count, setCount] = useState(0);
return (
<button
onClick={() => setCount(count + 1)}
type="button">
Click to add!
</button>
);
}
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>
);
}
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)
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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
}
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]);
}
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 });
}
// ...
}
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
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 ...
}