h e 1 1 o !
Effect Hook λ³Έλ¬Έ
π Side Effect
π μμν¨μλ?
- μμ ν¨μλ μ€μ§ ν¨μμ μ λ ₯(λ§€κ°λ³μ)λ§μ΄ ν¨μμ κ²°κ³Όμ μν₯μ μ£Όλ ν¨μμ λλ€. μ΄μ λ°λΌ μμ ν¨μλ νμ μμΈ‘ κ°λ₯ν λμΌν 리ν΄κ°μ μΆλ ₯ν©λλ€. Math.random() κ°μ λ©μλλ λμΌν μ λ ₯μλ λ€λ₯Έ μΆλ ₯μ΄ λμ¬ μ μμΌλ―λ‘ μμ ν¨μκ° μλλλ€.
- μ€μ§ λ§€κ°λ³μλ₯Ό ν΅ν΄ ν¨μ λ΄λΆλ‘ μ λ¬λ μΈμμκ²λ§ μμ‘΄ν΄ κ°μ μμ±ν΄ λ°ννλ ν¨μ
- μΈμλ₯Ό λ³κ²½νμ§ μλλ€.
- μΈλΆκ°μ λ§€κ°λ³μλ‘ μ λ¬ λ°μ μ μμ§λ§ λ³μλ κ°μ²΄ μ체λ₯Ό μ¬ν λΉ νκ±°λ λ³κ²½μν€λ κ²½μ°λ λΉμμ ν¨μμ΄λ€.
- μ΄λ€ μΈλΆ μνμλ μμ‘΄νμ§ μμΌλ©° μΈλΆ μνλ₯Ό λ³κ²½νμ§λ μλλ€.
- ν¨μ λ΄λΆμμ μΈλΆ μνλ₯Ό μ§μ μ°Έμ‘°νλ©΄ μΈλΆ μνμ μμ‘΄νκ² λμ΄ κ°μ΄ λ³ν μ μλ€.
- μ΄λ€ ν¨μκ° μλ²μ λ€νΈμν¬ μμ²μ 보λΈλ€λ©΄ μ΄λ‘ μΈν΄ μλ²μ λ°μ΄ν°μ Side Effectλ₯Ό μΌμΌν¬ μ μκ³ , μ΄μ λ°λΌ ν΄λΉ ν¨μλ μμ ν¨μκ° μλλ€.
π side effectλ?
- ν¨μ λ΄λΆμμ μΈλΆμ κ°μ κ΄μ¬νλ κ²½μ° Side λ€Effectκ° μλ€κ³ ν©λλ€. μμ ν¨μμ μΆλ ₯κ°μ μν₯μ λ―ΈμΉλ μμ λ€μ΄ λ°λ‘ Side EffectλΌκ³ ν μ μκ² μ΅λλ€. μμΌλ‘ μ¬λ¬λΆμ μ½λ©μ μμ΄μ Side Effectλ₯Ό μ΅μννκ±°λ λ°λ‘ λΆλ¦¬νμ¬ ν¨μλ‘ λ¬Άμ΄μ£Όλ μμ μ ν΄λΉ νλ‘μ νΈλ μννΈμ¨μ΄μ μ μ§λ³΄μλ₯Ό μ’ λ μμνκ² ν΄μ€λλ€.
"μ΄λ€ μ‘μ μ΄ λ€λ₯Έ μ‘μ μ μ λ°νλ©΄ side effect"
λ°μ΄ν° κ°μ Έμ€κΈ°, ꡬλ (subscription) μ€μ νκΈ°, μλμΌλ‘ React μ»΄ν¬λνΈμ DOMμ μμ νλ κ²κΉμ§ μ΄ λͺ¨λ κ²μ΄ side effects.
리μ‘νΈ μ»΄ν¬λνΈμμμ side effectλ νμ΄λ¨Έλ₯Ό μ¬μ©ν λ(setTimeout), λ°μ΄ν° κ°μ Έμ¬ λ(fetch API, AJAX μμ², localStorage), HTTP Request λ±μμ μΌμ΄λλ€. side Effectκ° μΌμ΄λλ κ²½μ°λ useEffectλ‘ λ£μ΄μ€μΌνλ€.
π μμ
λ€μ 보기μ sum ν¨μ μ€ μμ ν¨μμΈ κ²μ κ³ λ₯΄μΈμ.
//1
let c = 12;
function sum(a, b){
c = a * b;
return a + b;
}
//μΈλΆμ λ³μμΈ cλ₯Ό μ¬μ©
리μ‘νΈ μ»΄ν¬λνΈμμμ side effectλ νμ΄λ¨Έλ₯Ό μ¬μ©ν λ(setTimeout), λ°μ΄ν° κ°μ Έμ¬ λ(fetch API, AJAX μμ², localStorage) μΌμ΄λλ€. side Effectκ° μΌμ΄λλ κ²½μ°λ useEffectλ‘ λ£μ΄μ€μΌνλ€.
//2
const obj = {value: 12};
function sum(obj, num){
return {value: obj.value + num};
}
// κ°μ²΄ objλ₯Ό μΈμλ‘ λ°μμ μ¬μ©νλ€. κ°μ²΄ ν€κ°μ λ°κΎΈμ§ μκ³ , μΈμλ‘ λ°μμμΌλ μμν¨μ
//3
const obj = {value: 12};
function sum(obj, num){
obj.value += num;
}
//objλ₯Ό μΈμλ‘ λ°μμ§λ§ obj.value κ°μ μ¬ν λΉνκ³ μλ€. μΈλΆμ κ°μ²΄ κ°μ λ°κΎΈκ³ μμΌλ λΉμμ ν¨μμ΄λ€.
//4
Math.sqrt(x)
//xμ μ κ³±κ·Ό κ°μ νμ κ°λ€. μμν¨μμ΄λ€.
//5
Math.random()
// 0μ΄μ 1λ―Έλ§μ λμλ₯Ό λ§λλ ν¨μμ΄λ€. κ·Έ κ²°κ³Όκ° λ¬΄μμ΄ λ μ§ μμΈ‘ λΆκ°νκΈ° λλ¬Έμ λΉμμ ν¨μμ΄λ€.
π Effect Hook
Effect Hookμ μ¬μ©νλ©΄ ν¨μ μ»΄ν¬λνΈμμ side Effectλ₯Ό μνν μ μλ€.
π Effect Hook - useEffectμ μ€ν 쑰건
useEffectλ μ»΄ν¬λνΈκ° μλ‘ λ λλ§ λ λ μ€νλλ€.
μ»΄ν¬λνΈκ° μλ‘ λ λλ§λλ μΈ κ°μ§ κ²½μ°
- μ»΄ν¬λνΈ μμ± ν μ²μ νλ©΄μ λ λλ§
- μ»΄ν¬λνΈμ μλ‘μ΄ propsκ° μ λ¬λλ©° λ λλ§
- μ»΄ν¬λνΈμ μν(state)κ° λ°λλ©° λ λλ§
π hookμ μΈ λ μ£Όμ μ¬ν
- μ΅μμμμλ§ Hookμ νΈμΆνλ€propsκ° μ λ¬
- React ν¨μ λ΄μμ Hookμ νΈμΆνλ€
π useEffectμ νν
π 1. μΈμλ‘ μ½λ°±ν¨μλ₯Ό λ°μ
μ»΄ν¬λνΈκ° λ λλ§ λ λλ§λ€ μ½λ°±μ΄ μ€νλλ€.
(μ²μ λ§μ΄νΈ, λ€μ λλλ§ λ λλ§λ€ λ§€λ² μ½λ°± νΈμΆ)
μ½λ°±ν¨μλ λͺ¨λ μ»΄ν¬λνΈνκ° ν, μ€νλλ€(μμ‘΄μ±μ΄ λ°λ κ²½μ°)-> μ΄κ² λ λ§μ΄μ§?
π 2. μ½λ°±ν¨μμ λ°°μ΄(defendency array)μ λ°μ
μ²μ λ§μ΄νΈ, λ°°μ΄(κ°μ λͺ©λ‘) μ μμμ κ°μ΄ λ°λ λ μ€ν λλ€.
λ°°μ΄ μμ κ°μ΄ stateλ‘ μ λ°μ΄νΈ λλ κ²½μ°λ₯Ό μκ°νλ©΄ λλ€.
π 2-1. λΉ λ°°μ΄μΈ κ²½μ°, μ²μ λ§μ΄νΈ λλ§ μ½λ°± νΈμΆ
μ²μ λ¨ ν λ², μΈλΆ APIλ₯Ό ν΅ν΄ 리μμ€λ₯Ό λ°μμ€κ³ λ μ΄μ API νΈμΆμ΄ νμνμ§ μμ λμ μ¬μ©ν μ μλ€.
π μμ useEffectμ μΈ κ°μ§ νν
function App() {
const [keyword, setKeyword] = userState("");
const onChange = (event) => seyKeyword(event.target.value);
useEffect(() => {
console.log("λλ μ
λ°μ΄νΈκ° λ λλ§λ€ μλν΄") // 1
})
useEffect(() => {
console.log("λλ keywordκ° λ°λ λλ§λ€ μλν΄") // 2
},[keyword])
useEffect(() => {
console.log("λλ μ²μλ§ μλν΄") // 2-1
},[])
return (
<div>
<input
value={keyword}
onChange={onChange}
type="text"
placeholder="κ²μμ°½..."
/>
</div>
)
}
π Dependency Array
μ’ μμ± λ°°μ΄μ΄λ, useEffectμ λλ²μ§Έ μΈμλ‘ λ€μ΄κ°λ λ°°μ΄μ λ§νλ€.
Dependency Array(μ’ μμ± λ°°μ΄)μ effect hookμ 첫 λ²μ§Έ μΈμμΈ ν¨μκ° μ€νλλ 쑰건μ λ΄κ³ μλ λ λ²μ§Έ μΈμμ λλ€. useEffect(ν¨μ, [μ’ μμ±1, μ’ μμ±2, ...]) ννλ‘ λνλ΄μ΄μ§λ©° κ° μ’ μμ±μ ννμμ΄ μλ μ΄λ€ κ°μΌλ‘ ν λΉν©λλ€.
μ’ μμ± λ°°μ΄μ λ°λμ μ‘΄μ¬νμ§λ μμλ λ©λλ€. λ λ²μ§Έ μΈμλ₯Ό λΉμ°κ³ useEffect(ν¨μ)μ κΈ°λ³Έ ννλ‘λ§ μμ±νλ©΄, ν΄λΉ effect hookμ ν¨μλ λ€μ μΈ κ°μ§ 쑰건μ λ°λΌ μ€νλ©λλ€.
- μ»΄ν¬λνΈ μμ± ν μ²μ νλ©΄μ λ λλ§(νμ)
- μ»΄ν¬λνΈμ μλ‘μ΄ propsκ° μ λ¬λλ©° λ λλ§
- μ»΄ν¬λνΈμ μν(state)κ° λ°λλ©° λ λλ§
μ’ μμ± λ°°μ΄μ λ£μ΄μ€μΌ νλ κ²½μ° / μλ κ²½μ°κ° ν·κ°λ¦¬λ©΄ μλ λ§ν¬ μ°Έκ³
https://www.udemy.com/course/best-react/learn/lecture/28520645#questions
effect ν¨μμμ μ¬μ©νλ λͺ¨λ "κ²λ€"μ μΆκ°ν΄μΌ ν©λλ€. κ΅¬μ± μμ(λλ μΌλΆ μμ κ΅¬μ± μμ)κ° λ€μ λ λλ§ λμ΄ μ΄λ¬ν "κ²λ€"μ΄ λ³κ²½λ μ μλ κ²½μ°.κ·Έλ κΈ° λλ¬Έμ μ»΄ν¬λνΈ ν¨μμ μ μλ λ³μλ μν, μ»΄ν¬λνΈ ν¨μμ μ μλ props λλ ν¨μλ μ’ μμ±μΌλ‘ μΆκ°λμ΄μΌ ν©λλ€!
μ½κ² λ§ν΄, sideEffectμ μ½λ°±ν¨μμ κ²°κ³Όμ μν₯μ λ―ΈμΉλ κ²λ€μ λ£μΌλ©΄ λλ€.
π ν΄λ¦°μ
νμ΄λ¨Έ, μ΄λ²€νΈ 리μ€λ λ± ν¨μ λ§μΉκ³ μ’ λ£μμΌμ€
useEffect μμμ λ¦¬ν΄ κ°μΌλ‘ (μ 리νλ)ν¨μλ₯Ό λ£μ΄μ€λ€.
const Timer = (props) => {
useEffect(() => { // μ½λ°±ν¨μμ λ°°μ΄μ λ°λ useEffect
const timer = setInterval() => {
console.log('νμ΄λ¨Έ λμκ°λ μ€')
}, 1000);
return () => {
clearInterval(timer); //ν΄λ¦°μ
console.log('νμ΄λ¨Έ ν΄λ¦¬μ΄')
};
}, []); // λΉλ°°μ΄
return (
<div>
<span>νμ΄λ¨Έλ₯Ό μμν©λλ€></span>
</div>
);
};
μ¬μ΄λμ΄ννΈ ν¨μκ° μ€νλκΈ° μ μ μ€νλ¨.
π 리μ‘νΈμμ λ°μ΄ν°λ₯Ό νν°νλ λ κ°μ§ λ°©λ²
π μ»΄ν¬λνΈ λ΄μμ νν°λ§
μ²μ λ¨ ν λ², μΈλΆ APIλ‘λΆν° μ 체 λͺ©λ‘ λ°μ΄ν°λ₯Ό λΆλ¬μ€κ³ , λͺ©λ‘μ κ²μμ΄λ‘ filter νλ λ°©λ²
π μ»΄ν¬λνΈ μΈλΆμμ νν°λ§
μ»΄ν¬λνΈ μΈλΆλ‘ API μμ²μ ν λ, νν°λ§ ν κ²°κ³Όλ₯Ό λ°μμ€λ λ°©λ² (보ν΅, μλ²μ λ§€λ² κ²μμ΄μ ν¨κ» μμ²νλ κ²½μ°κ° μ΄μ ν΄λΉ)
π λλ°©μμ μ°¨μ΄μ
μ₯μ | λ¨μ | |
μ»΄ν¬λνΈ λ΄ | HTTP μμ²μ λΉλλ₯Ό μ€μΌ μ μλ€ | λΈλΌμ°μ (ν΄λΌμ΄μΈνΈ)μ λ©λͺ¨λ¦¬ μμ λ§μ λ°μ΄ν°λ₯Ό κ°κ² λλ―λ‘, ν΄λΌμ΄μΈνΈμ λΆλ΄μ΄ λμ΄λλ€ |
μ»΄ν¬λνΈ μΈ | ν΄λΌμ΄μΈνΈκ° νν°λ§ ꡬνμ μκ°νμ§ μμλ λλ€ | λΉλ²ν HTTP μμ²μ΄ μΌμ΄λκ² λλ©°, μλ²κ° νν°λ§μ μ²λ¦¬νλ―λ‘ μλ²κ° λΆλ΄μ κ°μ Έκ°λ€ |
π μμ 1. μ»΄ν¬λνΈ λ΄μμ νν°λ§
import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
export default function App() {
const [proverbs, setProverbs] = useState([]);
const [filter, setFilter] = useState("");
useEffect(() => {
console.log("μΈμ effect ν¨μκ° λΆλ¦΄κΉμ?");
const result = getProverbs();
setProverbs(result);
}, []);////////////////////////////////////////////// μ²μ λ λλ§ν λλ§ effect ν¨μκ° νΈμΆλ¨
const handleChange = (e) => {
setFilter(e.target.value);
};
return (
<div className="App">
νν°
<input type="text" value={filter} onChange={handleChange} />
<ul>
{proverbs
.filter((prvb) => {
return prvb.toLowerCase().includes(filter.toLowerCase()); //////////////μ§μ νν°ν΄μ λ£μ΄μ£Όκ³ μλ€
})
.map((prvb, i) => (
<Proverb saying={prvb} key={i} />
))}
</ul>
</div>
);
}
function Proverb({ saying }) {
return <li>{saying}</li>;
}
π μμ 2. μ»΄ν¬λνΈ μΈλΆμμ νν°λ§
import { useEffect, useState } from "react";
import "./styles.css";
import { getProverbs } from "./storageUtil";
export default function App() {
const [proverbs, setProverbs] = useState([]);
const [filter, setFilter] = useState("");
const [count, setCount] = useState(0);
useEffect(() => {
console.log("μΈμ effect ν¨μκ° λΆλ¦΄κΉμ?");
const result = getProverbs(filter);
setProverbs(result);
}, [filter]); // 3. μ’
μμ± λ°°μ΄μ filterλ₯Ό λ£μλ€. filterκ° κ°±μ λ λ λ§λ€ useeffect μμ ν¨μκ° μ€νλλ€
const handleChange = (e) => { // 2. μΈνμμ μ½μ΄μ¨ μ΄λ²€νΈ valueλ₯Ό setFilterμ λ£μ΄ filter κ°±μ
setFilter(e.target.value);
};
const handleCounterClick = () => {
setCount(count + 1);
};
return (
<div className="App">
νν°
<input type="text" value={filter} onChange={handleChange} /> // 1.μΈνμμ μ΄λ²€νΈλ₯Ό μ½κ³ μλ€
<ul>
{proverbs.map((prvb, i) => (
<Proverb saying={prvb} key={i} />
))}
</ul>
<button onClick={handleCounterClick}>μΉ΄μ΄ν° κ°: {count}</button>
</div>
);
}
function Proverb({ saying }) {
return <li>{saying}</li>;
}
π μ»΄ν¬λνΈ λ΄μμμ AJAX μμ²
fetchλ₯Ό μ¬μ©νλ€. λ¬Όλ‘ side effectλ₯Ό μΌμΌν€λ μ½λμ΄λ useEffectμ λ£μ΄μ€λ€.
λ°μ΄ν°λ₯Ό μ»μ΄μ€λ μλν¬μΈνΈλ₯Ό μ¬μ©νλ€.
useEffect(() => {
fetch(`http://μλ²μ£Όμ/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
});
}, [filter]);
π loading indicator
λͺ¨λ λ€νΈμν¬ μμ²μ΄ νμ μ¦κ°μ μΈ μλ΅μ κ°μ Έλ€μ£Όλ κ²μ μλλ€.
μΈλΆ API μ μμ΄ λ릴 κ²½μ°λ₯Ό κ³ λ €νμ¬, λ‘λ© νλ©΄(loading indicator)μ ꡬνμ νμμ .
Loading indicatorμ ꡬν μμ stateμ΄κ³ , side effectμ΄λ€.
const [isLoading, setIsLoading] = useState(true);
// μλ΅, LoadingIndicator μ»΄ν¬λνΈλ λ³λλ‘ κ΅¬ννμμ κ°μ ν©λλ€
return {isLoading ? <LoadingIndicator /> : <div>λ‘λ© μλ£ νλ©΄</div>}
μ»΄ν¬λνΈκ° ꡬνλλ 리ν΄λ¬Έ μμμ, Loading indicatorκ° λ‘λ© μλ£ νλ©΄μ λ체νλ€κ³ 보면 λλ€.
isLoadingμ΄ trueμ΄λ©΄ Loading indicatorκ° μΆλ ₯λκ³ , λ λλ§μ΄ λλκ³ isLoadingμ΄ falseμ΄λ©΄ λ‘λ©μλ£ νλ©΄μ΄ μΆλ ₯λλ€.
useEffect(() => {
setIsLoading(true);
fetch(`http://μλ²μ£Όμ/proverbs?q=${filter}`)
.then(resp => resp.json())
.then(result => {
setProverbs(result);
setIsLoading(false);
});
}, [filter]);
μμ μμμ²λΌ λ€νΈμν¬ ν΅μ μ ν΅ν΄ μλ²λ‘λΆν° λ°μ΄ν°λ₯Ό λ°λ κ²½μ° fetch μμ²μ μ νλ‘ setIsLoadingμ μ€μ ν΄ μ£Όμ΄ λ³΄λ€ λμ UXλ₯Ό ꡬνν μ μλ€.
π Reference
https://www.youtube.com/watch?v=kyodvzc5GHU
μ½λμ€ν μ΄μΈ
μ°Έκ³
'p r o g r a m m i n g' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
git μ€λ₯ / gitignore (0) | 2022.07.11 |
---|---|
chunk, buffer (0) | 2022.06.16 |
REST API μ±μλ λͺ¨λΈ(RMM), Open APIμ API Key (0) | 2022.06.10 |
HTTP/λ€νΈμν¬ κΈ°μ΄ - AJAX (0) | 2022.06.09 |
μ½νλ¦Ώ λ¬Έμ νμ΄ / insertDash (0) | 2022.06.08 |