๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŒŒ | WEB DEV/React

[React] 16. ์ปดํฌ๋„ŒํŠธ ์ „ํ™˜ํšจ๊ณผ ๋ถ€์—ฌํ•ด์ฃผ๊ธฐ

by KASSID 2024. 1. 13.

์ด์ „ ๊ธ€ โ–ผ

๋”๋ณด๊ธฐ

0. 2023.05.05 - [๐ŸŒŒ | WEB DEV/React] - [React] 0. React๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ  & ์ดˆ๊ธฐ ์„ธํŒ…

1. 2023.05.07 - [๐ŸŒŒ | WEB DEV/React] - [React] 1. JSX

2. 2023.05.26 - [๐ŸŒŒ | WEB DEV/React] - [React] 2. state (๋ณ€์ˆ˜, array, object)

2-1. 2023.05.27 - [๐ŸŒŒ | WEB DEV/React] - [React] 2-1. array state ์ •๋ ฌํ•˜๊ธฐ ( .sort()ํ™œ์šฉ)

3. 2023.05.28 - [๐ŸŒŒ | WEB DEV/React] - [React] 3. ์ปดํฌ๋„ŒํŠธ (Component)

4. 2023.05.28 - [๐ŸŒŒ | WEB DEV/React] - [React] 4. ๋™์ ์ธ UI ์ œ์ž‘ํ•˜๊ธฐ

5. 2023.05.28 - [๐ŸŒŒ | WEB DEV/React] - [React] 5. ๋ฐ˜๋ณต๋˜๋Š” ๋ถ€๋ถ„ ์ถ•์•ฝํ•˜๊ธฐ (map)

6. 2023.05.29 - [๐ŸŒŒ | WEB DEV/React] - [React] 6. props

7. 2023.07.03 - [๐ŸŒŒ | WEB DEV/React] - [React] 7. ์ด๋ฏธ์ง€ ์‚ฝ์ž…ํ•˜๊ธฐ(css, html, publicํด๋”์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ)

8. 2023.07.06 - [๐ŸŒŒ | WEB DEV/React] - [React] 8. ๋‹ค๋ฅธ ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ

9. 2023.07.09 - [๐ŸŒŒ | WEB DEV/React] - [React] 9. ๋ผ์šฐํŒ…-1 (react-router-dom์„ธํŒ…, Routes, Route, Link)

10. 2023.07.10 - [๐ŸŒŒ | WEB DEV/React] - [React] ๋ผ์šฐํŒ…-2 (useNavigate, 404page, Nested Routes, Outlet)

11. 2023.10.03 - [๐ŸŒŒ | WEB DEV/React] - [React] 11. ๋ผ์šฐํŒ…-3 ์–‘์‚ฐํ˜• ๋ผ์šฐํŒ…

12. 2023.10.04 - [๐ŸŒŒ | WEB DEV/React] - [React] 12. Styled-components (+ ํ•œ ์ปดํฌ๋„ŒํŠธ์— cssํŒŒ์ผ ์ ์šฉ๋ฒ•)

13. 2024.01.02 - [๐ŸŒŒ | WEB DEV/React] - [React] 13. ๋ฆฌ์•กํŠธ ์ปดํฌ๋„ŒํŠธ์˜ Lifecycle์™€ useEffect

14. 2024.01.12 - [๐ŸŒŒ | WEB DEV/React] - [React] 14. React์™€ ์„œ๋ฒ„ ์—ฐ๋™ํ•˜๊ธฐ (ajax๋ฅผ ์ด์šฉํ•ด! (get, post) )

15. 2024.01.13 - [๐ŸŒŒ | WEB DEV/React] - [React] 15. React ๋ฉ”๋‰ดํƒญ ๋งŒ๋“ค๊ธฐ (ํด๋ฆญ ์ด๋ฒคํŠธ์— ๋”ฐ๋ฅธ ๋‚ด์šฉ ๋ณ€๊ฒฝ)

 

์ปดํฌ๋„ŒํŠธ๋ฅผ ์ „ํ™˜ํ• ๋•Œ ํšจ๊ณผ๋ฅผ ๋„ฃ์–ด๋ณด์ž!

 

์ด์ „ ํฌ์ŠคํŠธ์™€ ์ด์–ด์ง‘๋‹ˆ๋‹ค!

2024.01.13 - [๐ŸŒŒ | WEB DEV/React] - [React] 15. React ๋ฉ”๋‰ดํƒญ ๋งŒ๋“ค๊ธฐ (ํด๋ฆญ ์ด๋ฒคํŠธ์— ๋”ฐ๋ฅธ ๋‚ด์šฉ ๋ณ€๊ฒฝ)

 

[React] 15. React ๋ฉ”๋‰ดํƒญ ๋งŒ๋“ค๊ธฐ (ํด๋ฆญ ์ด๋ฒคํŠธ์— ๋”ฐ๋ฅธ ๋‚ด์šฉ ๋ณ€๊ฒฝ)

์ด์ „ ๊ธ€ โ–ผ ๋”๋ณด๊ธฐ 0. 2023.05.05 - [๐ŸŒŒ | WEB DEV/React] - [React] 0. React๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ  & ์ดˆ๊ธฐ ์„ธํŒ… 1. 2023.05.07 - [๐ŸŒŒ | WEB DEV/React] - [React] 1. JSX 2. 2023.05.26 - [๐ŸŒŒ | WEB DEV/React] - [React] 2. state (๋ณ€์ˆ˜, array, obje

bluishhot-star.tistory.com

 

1. ์ „ํ™˜ํšจ๊ณผ๋ฅผ ์œ„ํ•œ 4step

์ปดํฌ๋„ŒํŠธ ์ „ํ™˜ ๊ณผ์ •์€ ์•„๋ž˜์˜ 4๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์„œ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋œ๋‹ค.

[์ „ํ™˜ํšจ๊ณผ 4step]
1) ๋™์ž‘ ์ „ style ๋‹ด์€ className ์ƒ์„ฑ
2) ๋™์ž‘ ํ›„ style ๋‹ด์„ className ์ƒ์„ฑ
3) transition ์†์„ฑ ์ถ”๊ฐ€
4) ์ƒํ™ฉ์— ๋”ฐ๋ฅธ 2)๋ฒˆ className ์ œ๊ฑฐor์ƒ์„ฑ

 

 


2. ์ œ์ž‘ ๋ฐฉ๋ฒ•

์•„๋ž˜์™€ ๊ฐ™์ด ๋ฉ”๋‰ด ํƒญ์„ ํด๋ฆญํ•˜๋ฉด ์•„๋ž˜์˜ ์ปจํ…์ธ  ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋ฐ”๋€Œ๊ณ , ์ด๋“ค์—๊ฒŒ ์ „ํ™˜ํšจ๊ณผ๋ฅผ ๋„ฃ์–ด๋ณด์ž.

 

 

1) ๋™์ž‘ ์ „ style ๋‹ด์€ className ์ƒ์„ฑ

.unselected{
  transform: scale(0);
}

 

2) ๋™์ž‘ ํ›„ style ๋‹ด์„ className ์ƒ์„ฑ

.selected{
  transform: scale(100%);
}

 

3) transition ์†์„ฑ ์ถ”๊ฐ€

0.3์ดˆ์˜ ์ „ํ™˜์‹œ๊ฐ„์„ ๋ถ€์—ฌํ•˜์˜€๋‹ค.

.selected{
  transform: scale(100%);
  transition: .3s
}

 

 

4) ์ƒํ™ฉ์— ๋”ฐ๋ฅธ 2)๋ฒˆ className ์ œ๊ฑฐor์ƒ์„ฑ

 

- className ๋‹ฌ์•„์ฃผ๊ธฐ

์ „ํ™˜ ์ „, ํ›„๋ฅผ ๋Œ€์ƒ ํƒœ๊ทธ์— ๋‹ฌ์•„์ค€ ํ›„,

์ „ํ™˜ ํ›„ style์„ ๋‹ด์€ className์„ ์ „ํ™˜ ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์‹œ ์ œ๊ฑฐ->์ƒ์„ฑํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

(์ „ํ™˜ ์ „: unselected, ์ „ํ™˜ ํ›„: selected)

...
<div className="tab-content">
  {
    <RenderTab idx={tabIdx}/>
  }
</div>
...

 

์œ„์˜ ๊ฒฝ์šฐ์—๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ์ž‘ํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์— <RenderTab/>์— className์„ ์ง์ ‘ ๋‹ค๋Š” ๊ฒƒ์ด ์•„๋‹Œ

์•„๋ž˜์ฒ˜๋Ÿผ ์‹ค์ œ๋กœ ๋ Œ๋”๋ง ๋˜๋Š” ํƒœ๊ทธ์— ๋‹ฌ์•„์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

function RenderTab({idx}){
  return(
    <div className={"unselected selected"}>
      {
        [ <Tab1/>,  <Tab2/>,  <Tab3/> ][idx]
      }
    </div>
  )
}

 

 

- className ์ œ์–ด

ํ‰์†Œ์—๋Š” selected๋ผ๋Š” className์ด ๋ถ™์–ด์žˆ์ง€ ์•Š์ง€๋งŒ

state๋ฅผ ์ด์šฉํ•ด์„œ tab์ด ๋ฐ”๋€Œ๋Š” ๊ฒฝ์šฐ ๋ถ™๋„๋ก ํ•ด๋ณด์ž.

 

className์„ ์ œ์–ดํ•  ๋•Œ ์ฃผ์˜ํ•  ์ ์€ "unselected "์ฒ˜๋Ÿผ ๊ณต๋ฐฑ์„ ๋‘์–ด์•ผํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

๋‘์ง€ ์•Š๋Š”๋‹ค๋ฉด "unselectedselected" ๋ผ๋Š” ํ•˜๋‚˜์˜ className์œผ๋กœ ์ธ์‹๋˜๊ธฐ ๋•Œ๋ฌธ์—

์›ํ•˜๋Š” style์„ ์ ์šฉํ•  ์ˆ˜ ์—†๋‹ค!

function RenderTab({idx}){
  const [pop, setPop] = useState("");
    
  useEffect(()=>{
    setTimeout(() => {
      setPop("selected");
    }, 100);
    return()=>{
      setPop("")
    }
  },[idx])

  return(
    <div className={"unselected " + pop}>
      {
        [ <Tab1/>,  <Tab2/>,  <Tab3/> ][idx]
      }
    </div>
  )
}

 

โ‘  ์ดˆ๊ธฐํ™”

pop ์ด๋ผ๋Š” state๋ฅผ ์ƒ์„ฑํ•ด์ค€ ๋’ค, "" ์œผ๋กœ ์ดˆ๊ธฐํ™”ํ•˜์˜€๋‹ค.

const [pop, setPop] = useState("");

 

โ‘ก ํด๋ฆญ ์‹œ (์ปดํฌ๋„ŒํŠธ ์ƒ์„ฑ)

setPop("") : "unselected " / setPop("selected") : "unselected selected" ์ด ๋˜๋„๋ก ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

useEffect(()=>{
  setPop("selected");
  return()=>{
    setPop("")
  }
},[idx])

 

ํด๋ฆญ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์‹œ, ๋™์ž‘ ์ „style, ๋™์ž‘ ํ›„ style์„ ์ˆœ์„œ๋Œ€๋กœ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด์„œ

setPop(""); setPop("selected"); ์ˆœ์œผ๋กœ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰์ด ๋˜์–ด์•ผ ํ•œ๋‹ค.

ํ•˜์ง€๋งŒ ์ด๋“ค์„ ๋ถ™์—ฌ์„œ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

๋”ฐ๋ผ์„œ clean up function์„ ์ด์šฉํ•˜๋ฉด useEffect ๋‚ด๋ถ€ ์ฝ”๋“œ ์ง์ „์— setPop("")์„ ๋จผ์ € ์‹คํ–‰ํ•œ ๋’ค,

useEffect ๋‚ด๋ถ€์—์„œ setPop("selected")๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค!

 

์ด๋ ‡๊ฒŒ๋งŒ ํ–ˆ๋‹ค๋ฉด ์—ญ์‹œ๋‚˜ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค..

setTimeout ๋“ฑ์„ ์ด์šฉํ•ด ์‹œ๊ฐ„์ฐจ๋ฅผ ๋‘์–ด state ๋ณ€ํ™”๋ฅผ ์ฃผ์–ด์•ผํ•œ๋‹ค.

useEffect(()=>{
  setTimeout(() => {
    setPop("selected");
  }, 100);
  return()=>{
    setPop("")
  }
},[idx])

 

์ด๋Š” React18์— ๋‚˜์˜จ ์‹ ๊ธฐ๋Šฅ์ธ automatic batching ๋•Œ๋ฌธ์ธ๋ฐ,

์ด๋กœ ์ธํ•ด state๋ฅผ ํ•œ๋ฒˆ์— ์—ฐ๋‹ฌ์•„์„œ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ• ๋•Œ, ๋ชจ๋“  state๋ฅผ ๋ณ€๊ฒฝํ•œ ํ›„ ๋งˆ์ง€๋ง‰์— ํ™”๋ฉด์ด ์žฌ๋ Œ๋”๋ง๋œ๋‹ค.

(setPop(""); setPop("selected");๋ฅผ ๋ถ™์—ฌ์„œ ์“ฐ๋ฉด ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์—†์—ˆ๋˜ ์ด์œ )

 

๊ทธ๋ ‡๊ธฐ์— ""์œผ๋กœ์˜ ์„ค์ •๊ณผ "selected"๋กœ์˜ ์„ค์ •์„ ๋ถ„๋ฆฌ์‹œ์ผœ์ฃผ์–ด์•ผํ•œ๋‹ค.

 

 

โ€ป flushSync ํ™œ์šฉํ•˜๊ธฐ

import { flushSync } from "react-dom"

useEffect(()=>{
  flushSync(()=>{setPop("");})
  setPop("selected")
},[idx])

setTimeout ๊ณผ cleanup function์„ ์ด์šฉํ–ˆ๋˜ ๋ฐฉ๋ฒ• ์™ธ์—๋„
flushSync()๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

์ด๋Š” aysnc await ์ฒ˜๋Ÿผ ๋น„๋™๊ธฐ ์ฝ”๋“œ๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ๋งŒ๋“ค์–ด์„œ
react์˜ ๋ฆฌ๋ Œ๋”๋ง์„ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค!

 

 

 

- ๊ฒฐ๊ณผ

๋Œ“๊ธ€