Frontend ๐Ÿ“š/React

[์ฝ”๋”ฉ์• ํ”Œ] ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ Part5 - Context API

leejaejae 2023. 10. 23. 18:01

๐Ÿ’‍โ™€๏ธ ํƒญ 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 ๋ฆฌ์•กํŠธ ๊ธฐ์ดˆ๋ถ€ํ„ฐ ์‡ผํ•‘๋ชฐ ํ”„๋กœ์ ํŠธ๊นŒ์ง€! >> ๊ฐ•์˜๋ฅผ ์ฐธ๊ณ ํ•ฉ๋‹ˆ๋‹ค.