์๋ช ์ฃผ๊ธฐ
์ปดํฌ๋ํธ๊ฐ ์์ฑ๋๊ณ , ๋ ๋๋ง ๋ ํ ์๋ฉธ๋ ๋๊น์ง์ ๊ณผ์ ์ ์๋ฏธํ๋ค.
์๋ช ์ฃผ๊ธฐ๋ Mount(ํ๋ฉด์ ๊ทธ๋ ค์ง) - Update(ํ๋ฉด ์ ๋ฐ์ดํธ) - Unmount(ํ๋ฉด์์ ์ฌ๋ผ์ง) ์ธ ๊ฐ์ง์ ๋จ๊ณ๋ก ์ด๋ฃจ์ด์ง๋ค.
ํด๋์คํ ์ปดํฌ๋ํธ ์๋ช ์ฃผ๊ธฐ
1. ์ปดํฌ๋ํธ ์ธ์คํด์ค ์์ฑ ๋ฐ ๋ง์ดํธ
์์ฑ๋ ์ธ์คํด์ค๊ฐ DOM์ ์ถ๊ฐ๋๋๋ฐ, ์ปดํฌ๋ํธ๊ฐ ํ์ํ ์ค์ ์ ํ๊ฑฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ฌ์ค๋ ๋ฑ์ ์ด๊ธฐ ์์ ์ด ์ํ๋๋ค.
- constructor() : ์ปดํฌ๋ํธ ์ธ์คํด์ค ์์ฑ ๋ฐ state ์ด๊ธฐํ
- render() : JSX ๋ฆฌํด, ํ๋ฉด์ ๊ทธ๋ฆด ๋ด์ฉ ์ ์
- componentDidMount() : ์ปดํฌ๋ํธ๊ฐ DOM์ ์ค์ ๋ก ๊ทธ๋ ค์ง ํ ํธ์ถ๋จ, ๋ฐ์ดํฐ ์์ฒญ / DOM ๊ด๋ จ ์์ / ํ์ด๋จธ๋ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ๋ฑ๋ก ๋ฑ์ ์ฌ์ฉ
2. ์ ๋ฐ์ดํธ
state๋ props ๋ฑ์ด ๋ณ๊ฒฝ๋๋ฉด ์ ๋ฐ์ดํธ ๋จ๊ณ๋ฅผ ๊ฐ๊ฒ ๋๋ค.
- shouldComponentUpdate() : ๋ฆฌ๋ ๋๋ง ์ฌ๋ถ๋ฅผ true, false๋ก ๊ฒฐ์
- render() : ๋ณ๊ฒฝ๋ ์ํ๋ฅผ ๋ฐ์ํ UI๋ฅผ ๊ทธ๋ฆฌ๋ ๋ฉ์๋
- componentDidUpdate() : ์ปดํฌ๋ํธ๊ฐ ์ ๋ฐ์ดํธ ๋ ์งํ ์คํ๋จ, API ํธ์ถ / DOM ์์ ์ ์ ์ฉ
3. ์ธ๋ง์ดํธ
์ปดํฌ๋ํธ๊ฐ ๋ ์ด์ ํ์์์ด์ง๋ฉด DOM์์ ์ ๊ฑฐ๋๋๋ฐ, ์ ๊ฑฐ๋๊ธฐ ์ ํ์ํ ์ ๋ฆฌ ์์ ์ ์ํํ๋ค.
- componentWillUnmount() : ์ปดํฌ๋ํธ๊ฐ ์ ๊ฑฐ๋๊ธฐ ์ ํธ์ถ๋จ, ํ์ด๋จธ ์ ๋ฆฌ / ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํด์ ๋ฑ ๋ชจ๋ ์ ๋ฆฌ ์์ ์ ์ํํ๋ค
* ์์
import { Component, useState } from 'react';
import './App.css';
function App() {
const [showCounter, setShowCounter] = useState(false);
return (
<>
{showCounter && <Counter />}
<br />
<button onClick={() => setShowCounter((prev) => !prev)}>show</button>
</>
);
}
class Counter extends Component {
// ์์ฑ์ ์์ฑ
constructor() {
super(); // ๋น์ด์์ด๋ ์จ์ค์ผ๋จ!
this.state = { counter: 1 };
console.log('constructor');
}
// ๋ง์ดํธ
componentDidMount() {
console.log('DidMount');
}
// ์
๋ฐ์ดํธ
componentDidUpdate() {
console.log('DidUpdate');
}
// ์ธ๋ง์ดํธ
componentWillUnmount() {
console.log('WillUnmount');
}
render() {
console.log('render');
return (
<>
<div>counter : {this.state.counter}</div>
<button
onClick={() =>
this.setState({
counter: this.state.counter + 1,
})
}>
+1
</button>
</>
);
}
}
export default App;
ํจ์ํ ์ปดํฌ๋ํธ ์๋ช ์ฃผ๊ธฐ
ํจ์ํ ์ปดํฌ๋ํธ์๋ ํด๋์คํ๊ณผ ๋ฌ๋ฆฌ ๋ณ๋๋ก state๋ฅผ ์ ์ํด์ฃผ๊ฑฐ๋ ์๋ช ์ฃผ๊ธฐ์ ๋ง์ถฐ ์ฝ๋๊ฐ ์คํ๋๋๋ก ํ๋ ๊ธฐ๋ฅ์ ๋ฐ๋ก ์๊ธฐ ๋๋ฌธ์, Effect Hook์ธ useEffect๋ฅผ ์ฌ์ฉํด์ ๊ธฐ๋ฅ์ ๋์ผํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
์ด ๋ ํด๋์คํ๊ณผ ๋ฌ๋ฆฌ ํจ์ํ ์ปดํฌ๋ํธ๋ ์ธ์คํด์ค๋ฅผ ๋ง๋ค๊ณ , ๋ง์ดํธ๋์ ๋ ์ํ ๋ณ๊ฒฝ์ด ์ผ์ด๋ ๊ฒฝ์ฐ ๋ด๋ถ๋ฅผ ๋ณ๊ฒฝํ๋ ํด๋์ค์ ๋ฌ๋ฆฌ ์์ ํธ์ถํ๋ ํจ์๋ฅผ ๋ ์ด์ ์ฌ์ฉํ์ง ์๊ณ , ์๋ก์ด ์ํ ๊ฐ์ผ๋ก ํจ์๋ฅผ ํธ์ถํ๋ค. ๊ธฐ์กด ํจ์๋ ์ฌ๋ผ์ง๊ณ ์๋ก์ด ํจ์ ํธ์ถ๋ก ๋์ฒด๋๋ฉฐ ๋ฆฌ๋ ๋๋ง๋๋ค.
ํด๋์คํ์์ componentDidMount, componentDidUpdate, componentWillUnmount ์ธ ๋จ๊ณ๋ก ๋๋์ด์ ธ ์๋ ๊ฒ๊ณผ๋ ๋ฌ๋ฆฌ, useEffect ํ๋๋ก ๋ค ๊ตฌํ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์ฝ๋๊ฐ ๋ ๊ฐ๊ฒฐํด์ง๋ค.
useEffect
์๋ช ์ฃผ๊ธฐ๋ฅผ ์ ์ดํ๋ ํ ์ผ๋ก, ๋ง์ดํธ + ์ ๋ฐ์ดํธ + ์ธ๋ง์ดํธ ๋ค ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค.
๊ธฐ๋ณธ ํํ
useEffect(()=>{
์ฒซ๋ฒ์งธ ์ธ์ : ํจ์ // useEffect๊ฐ ํธ์ถ๋๋ฉด ์คํ๋ ์ฝ๋
},[๋๋ฒ์งธ ์ธ์ : ๋ฐฐ์ด]) // useEffect๊ฐ ํธ์ถ๋๋ ์กฐ๊ฑด์ ์ ์ํด์ฃผ๋ ๋ฐฐ์ด
- ๋ฐฐ์ด์ ์ธ์๋ก ์ฃผ์ง ์์์ ๊ฒฝ์ฐ : ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง๋์ ๋, ๋ฆฌ๋ ๋๋ง ๋์ ๋ ์คํํ๊ฒ ๋๋ค. (๋ง์ดํธ, ์ ๋ฐ์ดํธํ ๋ useEffect()์คํ)
- ๋น ๋ฐฐ์ด์ ์ธ์๋ก ์คฌ์ ๊ฒฝ์ฐ : ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง๋์ ๋๋ง ์คํ (๋ง์ดํธ๋ ๋ useEffect() ์คํ)
- ๋ฐฐ์ด์ ๊ฐ์ ๋ด์ ์ธ์๋ก ์คฌ์ ๊ฒฝ์ฐ : ์ปดํฌ๋ํธ๊ฐ ์ฒ์ ๋ ๋๋ง ๋์ ๋, ๋ฐฐ์ด์ ๋ด๊ธด ๊ฐ์ด ๋ณ๊ฒฝ๋ผ ๋ฆฌ๋ ๋๋ง ๋์ ๋ ์คํ (๋ง์ดํธ, ์ ๋ฐ์ดํธํ ๋ useEffect()์คํ)
๊ทธ๋ผ ์ธ๋ง์ดํธ๋ ์ด๋ป๊ฒ ํ๋๋ฉด return()์ ์ฌ์ฉํ๋ฉด ๋๋ค. ์ฆ ์ปดํฌ๋ํธ๊ฐ ์ฌ๋ผ์ง ๋ return๋ด์ ํจ์๊ฐ ์คํ๋๋ ๊ฒ์ด๋ค.
useEffect(()=>{
์ฒซ๋ฒ์งธ ์ธ์ : ํจ์ // useEffect๊ฐ ํธ์ถ๋๋ฉด ์คํ๋ ์ฝ๋
return()=>{ ๋ฆฌํด๋๋ ํจ์ } // ์ธ๋ง์ดํธ๋ ๋
},[๋๋ฒ์งธ ์ธ์ : ๋ฐฐ์ด]) // useEffect๊ฐ ํธ์ถ๋๋ ์กฐ๊ฑด์ ์ ์ํด์ฃผ๋ ๋ฐฐ์ด
์์
1) ๋ฐฐ์ด ์ธ์๊ฐ ์์ ๊ฒฝ์ฐ
function Counter() {
const [counter, setCounter] = useState(0);
// useEffect
useEffect(() => {
// ๋ฐฐ์ด ์ธ์๊ฐ ์์ => ๋ง์ดํธ, ์
๋ฐ์ดํธ๊ฐ ์คํ
console.log('useEffect');
});
return (
<>
<div>counter : {counter}</div>
<button onClick={() => setCounter(counter + 1)}>+1</button>
</>
);
}
2) ์ธ์๋ก ๋น ๋ฐฐ์ด์ ์ ๋ฌํ ๊ฒฝ์ฐ
// useEffect
useEffect(() => {
console.log('useEffect');
}, []);
3) ๊ฐ์ด ์๋ ๋ฐฐ์ด์ ์ ๋ฌํ ๊ฒฝ์ฐ
๋ฐฐ์ด์ด ์์ ๋์ ์์๋์ ์ฐจ์ด๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํด ์๋ก์ด ์ํ๋ฅผ ํ๋ ๋ ์์ฑํ๋ค.
์ธ์๊ฐ์ผ๋ก๋ ์๋ก ์์ฑํ counter2์ ์ํ๊ฐ์ ๋ฃ์ด์คฌ๋ค.
function Counter() {
const [counter, setCounter] = useState(0);
const [counter2, setCounter2] = useState(100);
// useEffect
useEffect(() => {
console.log('useEffect');
}, [counter2]);
return (
<>
<div>counter : {counter}</div>
<button onClick={() => setCounter(counter + 1)}>+1</button>
<hr />
<div>counter2 : {counter2}</div>
<button onClick={() => setCounter2(counter2 - 1)}>-1</button>
</>
);
}
๋ง์ดํธ๋ ๋์, ์ธ์๋ก ๋ฃ์ counter2์ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง (์ ๋ฐ์ดํธํ ๋๋ง) useEffect๊ฐ ์คํ๋๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
4) ์ธ๋ง์ดํธ๋ ๋๋ ์ถ๊ฐํ๊ธฐ
์ธ๋ง์ดํธ ์ ์ ๋ฆฌ๋ฅผ ์ํด return๋ฌธ์ ์ถ๊ฐํ๋ค.
// useEffect
useEffect(() => {
console.log('useEffect');
return () => {
console.log('returned function');
};
}, [counter2]);
update์ค์๋ ๊ณ์ returned function์ด ์คํ๋๊ณ ์์์ ์ ์ ์๋๋ฐ,
์ด๋ ์ ๋ฐ์ดํธ - ์ธ๋ง์ดํธ๊ฐ ๋์์ ์ผ์ด๋ ๊ฒ์ด ์๋๋ผ ์์์ ์ธ๊ธํ๋ ๊ฒ์ฒ๋ผ ํจ์ํ ์ปดํฌ๋ํธ์์๋ ์ ๋ฐ์ดํธํ ๋ ๊ธฐ์กด ํจ์๊ฐ ์ญ์ ๋๊ณ ์๋ก์ด ํจ์๋ฅผ ํธ์ถํ๊ธฐ ๋๋ฌธ์ return๋ฌธ๋ ๊ฐ์ด ์คํ๋๊ณ ์๋ ๊ฒ์ด๋ค.
+ ์ด๋ ์์กด์ฑ ๋ฐฐ์ด์ ์์ ์ฃผ์ง ์์ผ๋ฉด ๊ตณ์ด returnํ๋ ์ด์ ๊ฐ ์์ด์ง๋ฏ๋ก, ์ ์ ํ๊ฒ ์์กด์ฑ ๋ฐฐ์ด์ ๋ฃ๋ ๊ฒ์ด ์ค์ํ๋ค.
+ ๋น๋ฐฐ์ด์ ์ธ์๋ก ๋ฃ์ผ๋ฉด unmount๋ ๋๋ง return๋ฌธ์ด ์คํ๋๊ฒ ๋๋ค.
clean-up ํจ์
useEffect์์ return์ผ๋ก ๋ฐํ๋ ํจ์๋ฅผ ํด๋ฆฐ์
ํจ์๋ผ๊ณ ํ๋๋ฐ, ๊ธฐ์กด ๋ฆฌ์์ค๋ฅผ ์ ๋ฆฌํ ๋ ์ฌ์ฉ๋๋ค.
React๊ฐ ์ปดํฌ๋ํธ์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ด๋ฆฌํ๋ฉด์ ์๋์ผ๋ก ์ด์ ์ effect๋ฅผ ์ ๋ฆฌ(clean-up)ํด์ฃผ๋ ๊ฒ์ด๋ค.
์์ ์์์์ ๊ณ์ returned function์ด ์ฝ์์ ์ถ๋ ฅ๋๋ ์ด์ ๋ ๊ณ์ ๋ ๋๋ง๋ ๋๋ง๋ค ๋ค์ useEffect๊ฐ ์คํ๋๊ธฐ ์ ์ ๊ธฐ์กด effect๋ฅผ ์ ๋ฆฌํ๋ ๊ฒ์ด๋ค.
์ผํ๋ณด๋ฉด ๊ทธ๋ฅ ์ธ๋ง์ดํธ์ ๋น์ทํ ์๋ ์์ง๋ง ํด๋ฆฐ์ ์ ๊ฒฝ์ฐ์๋ ์์กด์ฑ ๋ฐฐ์ด(๋๋ฒ์งธ ์ธ์๋ก ๋ฃ์ ๋ฐฐ์ด!)์ ํฌํจ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋๋, useEffect๊ฐ ์ฌ์คํ๋ ๋๋, ์ธ๋ง์ดํธ๋ ๋๋ ๋ฐ์ํ ์ ์๋ค.
์์กด์ฑ ๋ฐฐ์ด | cleanup ์คํ ์์ |
์๋ต | ๋ฆฌ๋ ๋๋ง ๋ ๋๋ง๋ค ๋ค์ ์คํ ์ cleanup ์คํ |
[] | unmount์์๋ง cleanup ์คํ |
[value] | value๊ฐ ๋ฐ๋ ๋๋ง๋ค, ๋ฐ๋๊ธฐ ์ cleanup ์คํ |
clean-up์ด ์๋์ผ๋ก ์คํ๋๋ ์ด์ ๋ ๋ฉ๋ชจ๋ฆฌ์ ๋์๋ฅผ ๋ฐฉ์งํ๊ณ , ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ ํ์ด๋จธ๋ฅผ ์ ๊ฑฐํ ์ ์๊ณ , ์์กด์ฑ ๋ฐฐ์ด์ ๊ฐ์ ์ค์ ํ ๊ฒฝ์ฐ ์ต์ ์ํ๋ฅผ ๋ฐ๋ก ๋ฐ์ํด ์ฌ๋ฐ๋ฅธ ์ํ๋ฅผ ์ ์งํ ์ ์๋ค.
์๋ช ์ฃผ๊ธฐ ํจ์์ ํ์์ฑ
์๋ช ์ฃผ๊ธฐ ํจ์๊ฐ ํ์ํ ์ด์ ๋ state๊ฐ ๋ฐ๋ ๋๋ง๋ค ์ด๋ฒคํธ ๋ฆฌ์คํฐ๋ ํ์ด๋จธ๋ฅผ ๋ฑ๋ก / ํด์ ํ๊ฑฐ๋, ๋ฐ์ดํฐ๋ฅผ ์๋ฒ์์ ๋ฐ์์ค๋ ๋ฑ์ ๋์์ ๊ด๋ฆฌํ๊ธฐ ์ํด์๋ค.
1. ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ฌ ๋ (API ์์ฒญ)
์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ฌ ๋๋ ๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌ ์ ํ๋ฉด ๋ฉ์ถค ํ์์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋ณดํต ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ก ์์ ํ๊ฒ ๋๋ค.
fetch()๋ ๋น๋๊ธฐ ํจ์๋ก, ๋ฐ์ดํฐ์ ์์ฒญ์ ๊ธฐ๋ค๋ฆฌ์ง ์์ ์ฑ ํ๋ก๋ฏธ์ค๋ฅผ ๋ฐํํ๊ณ , ๋ค์ ์ฝ๋๋ฅผ ์คํํ ๋ค ์๋ต์ด ์ค๋ฉด ๊ทธ๋ ์ฒ๋ฆฌํ๊ณ ์๋ค.
1) ์์
json-server : jsonํ์ผ์ ์ด์ฉํด ๋ชจ์์ฉ RESTful API ์๋ฒ ๋ฐ DB๋ฅผ ๊ตฌ์ถํ ์ ์๊ฒ ํด์ฃผ๋ ๋๊ตฌ๋ค.
๋ค์ ๋ช ๋ น์ด๋ก json-server๋ฅผ ์ค์นํ๋ค. ์ด ๋ -g๋ global์ ์๋ฏธํ๋ฉฐ ์ ์ญ์ผ๋ก ํจํค์ง๋ฅผ ์ค์นํ๊ฒ ๋ค๋ ์๋ฏธ๋ค.
npm i -g json-server
๊ทธ๋ฆฌ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ญํ ์ ํด์ค jsonํ์ผ์ ์๋ก ๋ง๋ค์๋ค.
db.json
{
"createOrder": [
{ "id": 1, "content": "npm create vite@latest my-app -- --template react" },
{ "id": 2, "content": "cd my-app" },
{ "id": 3, "content": "npm install" }
]
}
๊ทธ๋ฆฌ๊ณ json-server๋ฅผ ์คํํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค. db.jsonํ์ผ์ watching ํ๋ ๊ฒ์ด๋ค.
json-server --watch db.json
## ๊ธฐ๋ณธ ํฌํธ๋ 3000์ด๋ผ์ ๋ค์ --port 3004 ๋ฅผ ๋ถ์ด๋ฉด 3004๋ฒ ํฌํธ๋ก ๋ณ๊ฒฝํ ์ ์๋ค.
fetch ๋ฉ์๋๋ก ์คํํ json-server์ data๋ฅผ ์์ฒญํ๋ค.
๊ทธ๋ฆฌ๊ณ then์ผ๋ก ๋ฐ์์จ ์์ฒญ์ json()์ผ๋ก jsonํ์์ ์ ๋ ฅ๋ฐ์ => javascript ๊ฐ์ฒด๋ก ๋ฐํํ๊ณ data ๋ผ๋ ๋ณ์์ ํ ๋นํด์ค๋ค.
ํ ๋น๋ data๋ฅผ map()์ผ๋ก ํ๋ฉด์ ๋ฟ๋ ค์ฃผ๋ฉด...
function App() {
let data;
fetch('http://localhost:3000/data')
.then((res) => res.json())
.then((res) => (data = res));
return (
<>
<div>๋ฆฌ์กํธ ํ๋ก์ ํธ ๊ตฌ์ฑํ๊ธฐ</div>
{data.map((el) => (
<div key={el.id}>{el.content}</div>
))}
</>
);
}
data.map์์ data๊ฐ undefined ์ํ์ด๊ธฐ ๋๋ฌธ์ map()์ ์ฝ์ด์ฌ ์๊ฐ ์๋ค๋ ๊ฒ์ด๋ค...
fetch๊ฐ ๋น๋๊ธฐ ํจ์๊ธฐ ๋๋ฌธ์ ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ๋์ ์ปดํฌ๋ํธ๋ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ ๋จผ์ ๋ ๋๋ง๋๊ธฐ ๋๋ฌธ์ data๊ฐ undefined์ธ ์ํ๋ก ๋ ๋๋ง๋ ๊ฒ์ด๋ค.
๋๋ฌธ์ ์ด๋ด ๋๋ useState, useEffect๋ก ์ฒ๋ฆฌํด์ค ์ ์๋ค.
function App() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('http://localhost:3000/data')
.then((res) => res.json())
.then((res) => setData(res));
}, []);
return (
<>
<div>๋ฆฌ์กํธ ํ๋ก์ ํธ ๊ตฌ์ฑํ๊ธฐ</div>
{data.map((el) => (
<div key={el.id}>{el.content}</div>
))}
</>
);
}
useState๋ก data์ ์ํ๋ฅผ ๊ด๋ฆฌ
useEffect๋ก ์์กด์ฑ ๋ฐฐ์ด์ ๋น ๋ฐฐ์ด๋ก ์ค์ ํด ๋ง์ดํธ๋ ๋๋ง ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ด
data๋ฅผ ๋น ๋ฐฐ์ด๋ก ์ด๊ธฐํํ์ผ๋ฏ๋ก map์ ํธ์ถํ๊ธฐ ์ ์ data๊ฐ ๋ฐฐ์ด์ธ์ง ํ์ธ์ด ๊ฐ๋ฅ
* ์์กด์ฑ ๋ฐฐ์ด์ ๋น ๋ฐฐ์ด๋ก ์ค์ ํ๋ ์ด์
: ํ์ด์ง๊ฐ ์ฒ์ ๋ ๋๋ง ๋ ๋ ์๋ฒ๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ํ๊ธฐ ๋๋ฌธ์ fetch ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ณ ์๋๋ฐ, ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ๋์ ์ํ๊ฐ ๋ณํ๊ณ , ์ํ๊ฐ ๋ณํ๋ฉด ๊ณ์ํด์ ๋ฆฌ๋ ๋๋ง์ด ๋๋ฉด์ fetch()๊ฐ ๊ณ์ ์คํ์ด ๋๋๋ฐ, ์ด๋ ๋งค์ฐ ๋นํจ์จ์ ์ด๋ค.
๋๋ฌธ์ useEffect์ ์์กด์ฑ ๋ฐฐ์ด์ ๋น ๋ฐฐ์ด๋ก ์ค์ ํด ์ฒ์ ๋ง์ดํธ๋ ๋๋ง useEffect ๋ด์ ์ฝ๋ฐฑํจ์๊ฐ ์คํ์ด ๋๊ธฐ ๋๋ฌธ์ ํจ์จ์ ์ผ๋ก ๊ตฌ์ฑํ ์ ์๋ค.
2. ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ ๋
1) ๋ง์ฐ์ค ์ด๋ฒคํธ
useEffect์ useState๋ฅผ ์ด์ฉํด ๋ค์๊ณผ ๊ฐ์ด ๋ง์ฐ์ค๊ฐ ์์ง์ผ ๋๋ง๋ค ๋ง์ฐ์ค๋ฅผ ๋ฐ๋ผ์ค๋ div์์์ mouse์ ํ์ฌ ์์น๊ฐ์ ํ์ํด์ค ์ ์๋ค.
function App() {
return (
<>
<Mousefollower />
</>
);
}
// ๋ง์ฐ์ค ์ด๋ฒคํธ
const Mousefollower = () => {
// ๋ง์ฐ์ค์ ์ขํ ์ํ ์์ฑ
const [position, setPosition] = useState({ x: 0, y: 0 });
// ๋ง์ฐ์ค ์ด๋ฒคํธ ๋ฑ๋ก
useEffect(() => {
// ์ปดํฌ๋ํธ๊ฐ ๋ ๋๋ง๋ ๋๋ง๋ค (์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค) handleMouseMove๋ฅผ ๋ฑ๋ก
const handleMouseMove = (e) => {
// ์ขํ ์ํ๋ฅผ ๋ณ๊ฒฝ (e.clientX, e.clientY๋ ๋ธ๋ผ์ฐ์ ๊ธฐ์ค ๋ง์ฐ์ค ์ขํ๊ฐ)
setPosition({ x: e.clientX, y: e.clientY });
console.log('mouseMoved');
};
window.addEventListener('mouseover', handleMouseMove);
// ํด๋ฆฐ์
ํจ์, ์ํ๊ฐ ๋ณ๊ฒฝ๋๊ธฐ ์ง์ ๊ธฐ์กด ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ ๊ฑฐ๋๋ค
return () => {
window.removeEventListener('mouseover', handleMouseMove);
};
});
return (
<>
<div
style={{
position: 'fixed',
top: position.y,
left: position.x,
width: '20px',
height: '20px',
borderRadius: '50%',
background: 'green',
transform: 'translate(-50%, -50%)',
}}></div>
<p>
๋ง์ฐ์ค ์์น: {position.x}px, {position.y}px
</p>
</>
);
};
(์ด๋ ํด๋ฆฌ๋ ํจ์๋ก ์ด์ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋ก๋ฐ๋ก ์ ๊ฑฐํด์ฃผ์ง ์์ผ๋ฉด ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์์ฌ์ ์ฝ์์ฐฝ์ผ๋ก useEffect์ ์คํ ํ์๊ฐ ๊ธฐํ๊ธ์์ ์ผ๋ก ๋์ด๋๋ ๊ฑธ ๋ณผ ์ ์๋ค... )
2) ์คํฌ๋กค ์ด๋ฒคํธ
์คํฌ๋กค ์ขํ์ ๊ฒฝ์ฐ window๋ document์์ ๋ฐ๋ก ๊ฒฐ๊ณผ๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๊ธฐ ๋๋ฌธ์ ๋ง์ฐ์ค์ ๋ฌ๋ฆฌ ๊ตณ์ด ์ด๋ฒคํธ ๊ฐ์ฒด๋ฅผ ๊ฑฐ์น์น ์์๋ ๋๋ค. ๋ค๋ง ์คํฌ๋กค ์งํ๋๋ฅผ ํ์ํ๊ธฐ ์ํด ์ด๋ฒคํธ ๋ฆฌ์ค๋๊ฐ ์ฌ์ฉ๋์๋ค.
function App() {
return (
<>
<div style={{ height: '300vh' }}></div>
<Mousefollower />
<ScrollIndicator />
</>
);
}
const ScrollIndicator = () => {
// ์คํฌ๋กค ์งํ๋๋ฅผ ํ์ํ ๋ฐ์ ๋๋น ์ํ ์์ฑ
const [scrollWidth, setscrollWidth] = useState(0);
useEffect(() => {
// ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค ์คํฌ๋กค ์งํ๋ฅ ์ ๋ฐ์์ด
const handleScroll = () => {
// ์คํฌ๋กค ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
const scrollTop = window.scrollY;
const scrollHeight = document.documentElement.scrollHeight;
const clientHeight = document.documentElement.clientHeight;
const scrollPercentage = (scrollTop / (scrollHeight - clientHeight)) * 100;
// ๋ฐ์์จ ์งํ๋ฅ ์ ๋ฐ์ ๋๋น๋ก ์ค์
setscrollWidth(scrollPercentage);
};
// ์คํฌ๋กค ์ handleScroll ์คํ
window.addEventListener('scroll', handleScroll);
return () => { // ํด๋ฆฐ์
ํจ์!
window.removeEventListener('scroll', handleScroll);
};
});
return (
<>
<div
style={{
position: 'fixed',
top: 0,
left: 0,
width: `${scrollWidth}%`,
height: '10px',
background: 'green',
}}></div>
<div
style={{
position: 'fixed',
bottom: '50px',
left: '50%',
transform: 'translateX(-50%)',
}}>
์คํฌ๋กค ์งํ๋ : {scrollWidth.toFixed(0)}%
</div>
</>
);
};
3. ํ์ด๋จธ ํจ์๋ฅผ ์ฌ์ฉํ ๋
๋ค์ ์ฝ๋๋ 3์ด์์ ๋ฒํผ์ ๋๋ฅด์ง ์์ผ๋ฉด alert์ฐฝ์ ๋์์ค๋ค.
function App() {
return (
<>
<AlertTimer />
</>
);
}
// ์๊ฐ์ด ์ง๋๋ฉด alertํ๋ ํ์ด๋จธ ๊ฐ์ฒด
const AlertTimer = () => {
// alert์ ์ํ ์์ฑ
const [showAlert, setShowAlert] = useState(true);
useEffect(() => {
// 3์ด๊ฐ ์ง๋๋ฉด alert ์คํ
// setTimeout์ ํ์ด๋จธ ์์ด๋๋ฅผ ์ซ์ํ์
์ผ๋ก ๋ฐํํ๋ค.
const setTimeoutId = setTimeout(() => {
// showAlert๊ฐ true๋ผ๋ฉด alert, ์๋๋ฉด null
showAlert === true ? alert('์๊ฐ์ด๊ณผ') : null;
}, 3000);
return () => {
// ์์์ ๋ฐ์์จ ํ์ด๋จธ ์์ด๋ ์ธ์๋ก ๋๊ฒจ, ํด๋น ํ์ด๋จธ๋ฅผ ์ ๊ฑฐํ๊ฒ ํด์ค๋ค.
clearTimeout(setTimeoutId);
};
});
// 3์ด ์์ ๋ฒํผ์ ๋๋ฌ์ผ showAlert๊ฐ์ด false๋ก ๋ณ๊ฒฝ๋ผ alert ์ฐฝ์ด ์ด๋ฆฌ์ง ์์
return <button onClick={() => setShowAlert(false)}>๋นจ๋ฆฌ ํด๋ฆญ!!</button>;
};
+ ์ฌ๊ธฐ์ ์์กด์ฑ ๋ฐฐ์ด์ ๋ฃ๋ ๊ฒฝ์ฐ
[] : showAlert์ ์ด๊ธฐ๊ฐ(true)๋ฅผ ๊ธฐ์ตํ ์ํ๋ก ๋ง์ดํธํ ๋๋ง useEffect๊ฐ ์คํ๋๊ธฐ ๋๋ฌธ์ ๋ฒํผ์ ๋๋ฌ๋ 3์ด ๋ค์ alert์ฐฝ์ ๋์ด๋ค.
[showAlert] - ๋ฒํผ์ ๋๋ฅธ ๊ฒฝ์ฐ :
- showAlert ๊ฐ์ด true → false๋ก ๋ณํ
- ์์กด์ฑ ๋ฐฐ์ด [showAlert]์ ์ํด useEffect ์ฌ์คํ, ์ด์ ํ์ด๋จธ๋ ํด๋ฆฐ์ ํจ์๋ก ์ ๊ฑฐ๋๊ณ ์๋ก์ด setTimeout์ด ์ฌ์คํ๋จ
- ๊ทธ๋ฌ๋ showAlert = false์ด๋ฏ๋ก 3์ด๋ค์ ์กฐ๊ฑด์ ๊ฑธ๋ ค alert๊ฐ ์คํ์ด ๋์ง ์์ ์ํ๋ก ๋๋๋ค
[showAlert] - ๋ฒํผ์ ๋๋ฅด์ง ์์ ๊ฒฝ์ฐ :
- showAlert ๊ฐ์ด ๋ณํํ์ง ์์
- 3์ด ๋ค์ alert์ฐฝ์ ๋์, ๊ทธ๋ฆฌ๊ณ ์ํ๊ฐ ๋ณํ๋์ง ์๊ธฐ ๋๋ฌธ์ ๊ทธ๋๋ก ์ข ๋ฃ
์์กด์ฑ ๋ฐฐ์ด์ []๋ก ๋น์ธ๊ฑฐ๋ฉด useRef๋ก ์ฐ๋๊ฒ ๋์๋ฐ, ์ด๋ ๋ค์ ๊ธ๋ก...
์ฐธ๊ณ
ํด๋์คํ ์ปดํฌ๋ํธ ์๋ช ์ฃผ๊ธฐ : https://ko.legacy.reactjs.org/docs/state-and-lifecycle.html
Effect Hook : https://ko.legacy.reactjs.org/docs/react-component.html
, https://ko.legacy.reactjs.org/docs/hooks-effect.html
์ด๋ฏธ์ง ์ถ์ฒ
class component : https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
function component : https://wavez.github.io/react-hooks-lifecycle/
'react' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
React / custom Hook (1) | 2025.04.11 |
---|---|
React / useRef (0) | 2025.04.11 |
React / Router ์ค์ต - ๋๋ฌผ ์ ๋ณด ์ฌ์ดํธ ๋ง๋ค๊ธฐ (0) | 2025.04.09 |
React / Router (0) | 2025.04.09 |
React / ์กฐ๊ฑด๋ถ ๋ ๋๋ง (0) | 2025.04.09 |