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

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

by KASSID 2024. 1. 13.

๋ชฉ์ฐจ

    728x90

    ์ด์ „ ๊ธ€ โ–ผ

    ๋”๋ณด๊ธฐ

    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์˜ ๋ฆฌ๋ Œ๋”๋ง์„ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค!

     

     

     

    - ๊ฒฐ๊ณผ

    ๋Œ“๊ธ€