๐โ๏ธ ํญ UI ๋ง๋ค๊ธฐ
1. html css๋ก ํญ ๋์์ธ ๋ฏธ๋ฆฌ ์์ฑํ๊ธฐ
<Nav variant="tabs" defaultActiveKey="link0">
<Nav.Item>
<Nav.Link onClick={()=>{ ํญ๋ณ๊ฒฝ(0) }} eventKey="link0">๋ฒํผ0</Nav.Link>
<!-- ๋ฒํผ ๋๋ฅผ ๋ ๋ง๋ค ์ํ๋ ํญ ๋ด์ฉ -->
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={()=>{ ํญ๋ณ๊ฒฝ(1) }} eventKey="link1">๋ฒํผ1</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link onClick={()=>{ ํญ๋ณ๊ฒฝ(2) }} eventKey="link2">๋ฒํผ2</Nav.Link>
</Nav.Item>
</Nav>
<div>๋ด์ฉ0</div>
<div>๋ด์ฉ1</div>
<div>๋ด์ฉ2</div>
2. UI์ ํ์ฌ ์ํ๋ฅผ ์ ์ฅํ state ํ๋ ๋ง๋ค๊ธฐ
function Detail(){
let [ํญ, ํญ๋ณ๊ฒฝ] = useState(0)
(์๋ต)
}
3. state์ ๋ฐ๋ผ์ UI๊ฐ ์ด๋ป๊ฒ ๋ณด์ผ์ง ์์ฑ
function Detail(){
let [ํญ, ํญ๋ณ๊ฒฝ] = useState(0)
return (
<TabContent ํญ={ํญ}/>
)
}
function TabContent(props){ // detail ์์ ์๋ state ์ฌ์ฉํ๊ธฐ ์ํด props
if (props.ํญ === 0){
return <div>๋ด์ฉ0</div>
}
if (props.ํญ === 1){
return <div>๋ด์ฉ1</div>
}
if (props.ํญ === 2){
return <div>๋ด์ฉ2</div>
}
}
๐โ๏ธ ์ปดํฌ๋ํธ ์ ํ ์ ๋๋ฉ์ด์
1. ์ ๋๋ฉ์ด์
๋์ ์ ์คํ์ผ์ ๋ด์ className ๋ง๋ค๊ธฐ
2. ์ ๋๋ฉ์ด์
๋์ ํ ์คํ์ผ์ ๋ด์ className ๋ง๋ค๊ธฐ
.start {
opacity : 0
}
.end {
opacity : 1;
}
3. transition ์์ฑ ์ถ๊ฐ
.start {
opacity : 0
}
.end {
opacity : 1;
transition : opacity 0.5s;
}
- transition์ “ํด๋น ์์ฑ์ด ๋ณํ ๋ ์์ํ ๋ณ๊ฒฝํด์ฃผ์ธ์“ ๋ผ๋ ๋ป์ด๋ค
- ์ด์ ์ํ๋ <div> ์์์ start ๋ฃ์ด๋๊ณ end๋ฅผ ํ๋ถ์ฐฉํ ๋๋ง๋ค fade in ๋๋ค.
4. ์ํ ๋ end ๋ถ์ฐฉ
function TabContent({ํญ}){
let [fade, setFade] = useState('')
useEffect(()=>{
setTImeout(()=>{ setFade('end') }, 100)
return ()=>{
setFade('') // useEffect ์คํ ์ ์ 'end'๊ฐ ''๋ก ๋ฐ๋
}
}, [ํญ])
return (
<div className={'start ' + fade}>
{ [<div>๋ด์ฉ0</div>, <div>๋ด์ฉ1</div>, <div>๋ด์ฉ2</div>][ํญ] }
</div>
)
}
- setTimeout ์ฐ๋ ์ด์ : ๋ฆฌ์กํธ 18๋ฒ์ ์ด์๋ถํฐ๋ automatic batch๋ผ๋ ๊ธฐ๋ฅ์ด ์๊ฒผ๋ค. state ๋ณ๊ฒฝ ํจ์๋ค์ด ์ฐ๋ฌ์์ ์ฌ๋ฌ๊ฐ ์ฒ๋ฆฌ๋์ด์ผํ๋ค๋ฉด state ๋ณ๊ฒฝํจ์๋ฅผ ๋ค ์ฒ๋ฆฌํ๊ณ ๋ง์ง๋ง์ ํ ๋ฒ๋ง ์ฌ๋ ๋๋ง๋จ. ๊ทธ๋์ 'end'๋ก ๋ณ๊ฒฝํ๋๊ฑฐ๋ '' ์ด๊ฑธ๋ก ๋ณ๊ฒฝํ๋๊ฑฐ๋ ์ฝ๊ฐ ์๊ฐ์ฐจ๋ฅผ ๋ ๊ฒ! (์ด ๋ฐ์๋ flushsync() ๊ฐ์ ๊ฑฐ ์จ๋ ๋จ. automatic batching์ ๋ง์์ค)
โ๏ธ Context API
- App์ ์๋ state๋ฅผ TabContent ์ปดํฌ๋ํธ์์ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด App → Detail → TabContent ์ด๋ ๊ฒ props๋ฅผ 2๋ฒ ์ ์กํด์ผํ๋๋ฐ ์ด๋ฅผ ๋ณด๋ค ๊ฐ๋จํ๊ฒ ์ ์กํ๋ ๋ฐฉ๋ฒ์ผ๋ก๋ Context API๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ Redux ๊ฐ์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
- ์ค๋์ ๊ทธ ์ค Context API๋ฅผ ๊ณต๋ถํด๋ณด์.
โ๏ธ Context API ๋ฌธ๋ฒ์ผ๋ก props ์์ด state ๊ณต์ ํ๊ธฐ
- Context API ๋ฌธ๋ฒ์ ์ฐ๋ฉด props ์ ์ก์์ด๋ TabContent ์ปดํฌ๋ํธ๋ฅผ ์ธ ์ ์๋๋ฐ ๋จผ์ ์๋์ ๊ฐ์ด ์
ํ
์ ํด์ผํ๋ค.
(App.js)
export let Context1 = React.createContext(); // createContext() ํจ์๋ฅผ ๊ฐ์ ธ์์ context๋ฅผ ํ๋ ๋ง๋ค์ด์ค๋ค.(= state ๋ณด๊ดํจ)
function App(){
let [์ฌ๊ณ , ์ฌ๊ณ ๋ณ๊ฒฝ] = useState([10,11,12]);
return (
<Context1.Provider value={ {์ฌ๊ณ , shoes} }> <!-- ์๊น ๋ง๋ Context1๋ก ์ํ๋ ๊ณณ์ ๊ฐ์ธ๊ณ ๊ณต์ ๋ฅผ ์ํ๋ state๋ฅผ value์์ ๋ค ์ ๋๋ค -->
<Detail shoes={shoes}/> <!-- Context1๋ก ๊ฐ์ผ ๋ชจ๋ ์ปดํฌ๋ํธ์ ๊ทธ ์์์ปดํฌ๋ํธ๋ state๋ฅผ props ์ ์ก์์ด ์ง์ ์ฌ์ฉ ๊ฐ๋ฅ -->
</Context1.Provider>
)
}
โ๏ธ Context ์์ ์๋ state ์ฌ์ฉํ๋ ค๋ฉด
1. ๋ง๋ค์ด๋ Context๋ฅผ import ํด์จ๋ค.
2. useContext() ์์ ๋ฃ๋๋ค.
- ๊ทธ๋ผ ์ด์ ๊ทธ ์๋ฆฌ์ ๊ณต์ ํ๋ state๊ฐ ์ ๋ถ ๋จ๋๋ฐ ๊ทธ๊ฑฐ ์ฐ๋ฉด ๋๋ค.
// Detail.js
import {useState, useEffect, useContext} from 'react';
import {Context1} from './../App.js'; // Context1 import
function Detail(){
let {์ฌ๊ณ } = useContext(Context1) // useContext() ์์ ๋ด์ผ๋ฉด Context ํด์ฒดํด์ฃผ๊ณ ๊ทธ ์๋ฆฌ์ ๊ณต์ ํ๋ ๋ชจ๋ state๊ฐ ๋จ๋๋ค.
return (
<div>{์ฌ๊ณ }</div>
)
}
โ๏ธ Context API ๋จ์
- ์ค์ฒฉํด์ ์ฌ์ฉํ ์ปดํฌ๋ํธ๊ฐ ๋ง์ ๋ ํธ๋ฆฌํ ๋ฌธ๋ฒ์.
- state ๋ณ๊ฒฝ์ ์ธ๋ฐ์๋ ์ปดํฌ๋ํธ๊น์ง ์ ๋ถ ์ฌ๋ ๋๋ง๋๊ณ
- useContext() ๋ฅผ ์ฐ๊ณ ์๋ ์ปดํฌ๋ํธ๋ ๋์ค์ ๋ค๋ฅธ ํ์ผ์์ ์ฌ์ฌ์ฉํ ๋ Context๋ฅผ import ํ๋๊ฒ ๊ท์ฐฎ์์ง ์ ์์.
- ๊ทธ๋์ ์ด๊ฒ๋ณด๋ค Redux๊ฐ์ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ง์ด ์ฌ์ฉ.
๋ณธ ํฌ์คํ ์ << React ๋ฆฌ์กํธ ๊ธฐ์ด๋ถํฐ ์ผํ๋ชฐ ํ๋ก์ ํธ๊น์ง! >> ๊ฐ์๋ฅผ ์ฐธ๊ณ ํฉ๋๋ค.