๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
[๊ฐœ๋ฐœ] Practice/React

[React] Tab ๋งŒ๋“ค๊ณ  ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ถ”๊ฐ€ํ•˜๊ธฐ

by Connecting-the-dots 2022. 3. 27.
728x90
๋ฐ˜์‘ํ˜•

๐Ÿ’ก ์‹ค์Šต ํฌ์ธํŠธ!


๐Ÿ’œ Tab ๋งŒ๋“ค๊ธฐ ์ „์— ์ƒ๊ฐํ•ด๋ณด๊ธฐ

function Detail(){

  return (
    <div>
    
      <button>์ƒ์„ธ์ •๋ณด</button>
      <button>๋ฆฌ๋ทฐ</button>
      <button>Q&A</button>
      
      <div>์ƒ์„ธ์ •๋ณด ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
      <div>๋ฆฌ๋ทฐ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
      <div>Q&A ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
      
    </div>
  )
}
  • 3๊ฐœ์˜ ํƒญ์œผ๋กœ ๊ตฌ์„ฑํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ, ํด๋ฆญํ•  ๋ฒ„ํŠผ ํƒœ๊ทธ 3๊ฐœ์™€ ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ณด์—ฌ์ค„ ๋‚ด์šฉ์ด ๋“ค์–ด๊ฐˆ div ํƒœ๊ทธ๊ฐ€ 3๊ฐœ ์žˆ๋Š” UI ๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด์ œ ๊ฑฐ๊ธฐ์„œ ๊ฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ•ด๋‹น ๋ฒ„ํŠผ์— ๋งž๋Š” div ํƒœ๊ทธ๋ฅผ ๋ณด์—ฌ์ฃผ๋ฉด ๋œ๋‹ค.
  • ๋”ฐ๋ผ์„œ, ๋ช‡ ๋ฒˆ์งธ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋Š”์ง€ state ๋กœ ์ €์žฅํ•ด๋‘๊ณ , state ์— ๋”ฐ๋ผ ์•Œ๋งž์€ div ๋ฐ•์Šค๋ฅผ ๋ณด์ด๋„๋ก ํ˜น์€ ๋ณด์ด์ง€ ์•Š๋„๋ก ์ฒ˜๋ฆฌํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

๐Ÿ’œ Tab UI ๋””์ž์ธํ•˜๊ธฐ

  • ๋น ๋ฅธ ๋””์ž์ธ์„ ์œ„ํ•ด์„œ React Bootstrap ์—์„œ Tabs ๋ฅผ ๊ฒ€์ƒ‰ํ•ด์„œ ๋งˆ์Œ์— ๋“œ๋Š” ๋””์ž์ธ์„ ๋ณต์‚ฌํ•˜์—ฌ Detail.js ํŒŒ์ผ์— ๋ถ™์—ฌ๋„ฃ๊ธฐํ•ด์ฃผ์—ˆ๋‹ค.

 

import {Nav} from 'react-bootstrap';
  • React Bootstrap ์—์„œ ์›ํ•˜๋Š” ๋””์ž์ธ์„ ๊ฐ€์ ธ์˜ฌ ๋•Œ๋Š” ๊ฐ€์ ธ์˜จ Component ๋ฅผ ๊ผญ import ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

 

  <Nav className="mt-5" variant="tabs" defaultActiveKey="0">
    <Nav.Item>
      <Nav.Link eventKey="0">์ƒ์„ธ์ •๋ณด</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="1">๋ฆฌ๋ทฐ</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="2">Q&A</Nav.Link>
    </Nav.Item>
  </Nav>

  <div>์ƒ์„ธ์ •๋ณด ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
  <div>๋ฆฌ๋ทฐ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
  <div>Q&A ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
  • ์šฐ์„ , eventKey ๋ผ๋Š” ์†์„ฑ์— ๊ฐ๊ฐ ๋‹ค๋ฅธ ๊ฐ’์„ ์ž…๋ ฅํ•˜์—ฌ ๊ฐ ํƒญ๋“ค์„ ๊ตฌ๋ณ„ํ•ด์ฃผ์—ˆ๋‹ค.
  • ๋‹ค์Œ์œผ๋กœ ๊ธฐ๋ณธ์œผ๋กœ ํ™œ์„ฑํ™”๋  ํƒญ์„ ์ •ํ•˜๋Š” ๋ถ€๋ถ„์ธ defaultActiveKey ๋ฅผ ์ •ํ•ด์ฃผ๋ฉด ๋˜๋Š”๋ฐ ๋‚˜๋Š” ๋งจ ์ฒ˜์Œ์— eventKey ๊ฐ€ 0 ์ธ ํƒญ์„ ๋ณด์—ฌ์ฃผ๋„๋ก defaultActiveKey='0' ์œผ๋กœ ์ž‘์„ฑํ–ˆ๋‹ค.

 

  • ์ด์ œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋กœ ํ™•์ธํ•˜๋ฉด ์œ„์™€ ๊ฐ™์ด ํƒญ UI ๊ฐ€ ์ƒ์„ฑ๋œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ’œ Tab ๊ธฐ๋Šฅ ๊ฐœ๋ฐœํ•˜๊ธฐ

๐Ÿค Tab UI ์˜ ์ƒํƒœ๋ฅผ ์ €์žฅํ•  state ๋งŒ๋“ค๊ธฐ

  • ์ด์ œ ๊ฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํ•ด๋‹นํ•˜๋Š” div ๋ฐ•์Šค๋ฅผ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ด๋–ค ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €๋Š”์ง€ ์ €์žฅํ•ด์ค„ state ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.
  • ์ฆ‰, ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด state ๊ฐ€ 0, 1, 2 ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฐ”๋€Œ์–ด ์ €์žฅ๋˜๋ฉด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.
let [clickedTab, setClickedTab] = useState(0);
  • ๊ทธ๋ž˜์„œ clickedTab ์ด๋ผ๋Š” state ๋ฅผ ๋งŒ๋“ค์–ด์„œ ์ดˆ๊ธฐ๊ฐ’์„ 0์œผ๋กœ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค.

๐Ÿค onClick ์†์„ฑ์œผ๋กœ ํด๋ฆญํ•œ Tab ์˜ ๋ฒˆํ˜ธ๋กœ state ๋ณ€๊ฒฝํ•ด์ฃผ๊ธฐ

  <Nav className="mt-5" variant="tabs" defaultActiveKey="0">
    <Nav.Item>
      <Nav.Link eventKey="0" onClick={()=>{setClickedTab(0)}}>์ƒ์„ธ์ •๋ณด</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="1" onClick={()=>{setClickedTab(1)}}>๋ฆฌ๋ทฐ</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="2" onClick={()=>{setClickedTab(2)}}>Q&A</Nav.Link>
    </Nav.Item>
  </Nav>
  
  <div>์ƒ์„ธ์ •๋ณด ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
  <div>๋ฆฌ๋ทฐ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
  <div>Q&A ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</div>
  • ์ด์ œ ๊ฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด setClickedTab() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด clickedTab ์— ์ €์žฅ๋œ ๊ฐ’์„ ํด๋ฆญํ•œ ๋ฒ„ํŠผ์˜ ๋ฒˆํ˜ธ๋กœ ๋ฐ”๋€Œ๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.
  • ์ฆ‰, 0๋ฒˆ ํƒญ์„ ํด๋ฆญํ•˜๋ฉด clickedTab ์ด๋ผ๋Š” state ๊ฐ€ 0 ์ด ๋˜๊ณ , 1๋ฒˆ ํƒญ์„ ํด๋ฆญํ•˜๋ฉด 1์ด ๋˜๋Š” ์‹์ด๋‹ค.

๐Ÿค state ์— ์ €์žฅ๋œ ๊ฐ’์— ๋งž์ถฐ div ๋ฐ•์Šค ๋ณด์—ฌ์ฃผ๊ธฐ

  <Nav className="mt-5" variant="tabs" defaultActiveKey="0">
    <Nav.Item>
      <Nav.Link eventKey="0" onClick={()=>{setClickedTab(0)}}>์ƒ์„ธ์ •๋ณด</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="1" onClick={()=>{setClickedTab(1)}}>๋ฆฌ๋ทฐ</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="2" onClick={()=>{setClickedTab(2)}}>Q&A</Nav.Link>
    </Nav.Item>
  </Nav>
  
  <TabContent clickedTab={clickedTab}/>
  • ์ด์ œ ๊ฐ ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ clickedTab ์— ์ €์žฅ๋œ ๊ฐ’๊ณผ ์ผ์น˜ํ•˜๋Š” div ๋ฐ•์Šค๋ฅผ ๋ณด์—ฌ์ฃผ์–ด์•ผ ํ•œ๋‹ค.
  • ์ฆ‰, clickedTab ์ด๋ผ๋Š” state ๊ฐ€ 0 ์ด ๋˜๋ฉด 0๋ฒˆ div ๋ฐ•์Šค๋ฅผ ๋ณด์—ฌ์ฃผ๊ณ , 1 ์ด ๋˜๋ฉด 1๋ฒˆ div ๋ฐ•์Šค๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์‹์ด๋‹ค.
  • ๋‚˜๋Š” ์ด๋ฅผ if ๋ฌธ์œผ๋กœ ์ž‘์„ฑํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ TabContent ๋ผ๋Š” Component ๋ฅผ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  ์ด Component ์—๋Š” clickedTab ์ด๋ผ๋Š” state ๋ฅผ ์กฐ๊ฑด์‹์— ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋ฏ€๋กœ props ๋ฌธ๋ฒ•์„ ์ด์šฉํ•ด clickedTab ์ด๋ผ๋Š” ๋ณ€์ˆ˜๋ช…์œผ๋กœ clickedTab ์ด๋ผ๋Š” state ๋ฅผ TabContent Component ๋กœ ์ „์†กํ•ด์ฃผ์—ˆ๋‹ค.

 

 

 

function TabContent(props) {

  if (props.clickedTab === 0){
    return (<TabContentTitle className="mt-5">์ƒ์„ธ์ •๋ณด ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  } else if (props.clickedTab === 1) {
    return (<TabContentTitle  className="mt-5">๋ฆฌ๋ทฐ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  } else if (props.clickedTab === 2) {
    return (<TabContentTitle className="mt-5">Q&A ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  }
}
  • ์ด์ œ TabContent ์—์„œ clickedTab ์ด๋ผ๋Š” state ๋ฅผ props ๋กœ ๋ฐ›์•„์˜จ ํ›„, if ๋ฌธ์„ ์ž‘์„ฑํ•ด์ฃผ์—ˆ๋‹ค.
  • if ๋ฌธ ๋ถ€๋ถ„์€ ํ•ด์„์ด ์–ด๋ ต์ง€ ์•Š์œผ๋‹ˆ ์„ค๋ช…์€ ์ƒ๋žต!

 

let TabContentTitle = styled.div`
  font-size: 30px;
  font-weight: bold;
  background: #eee;
  padding:200px 0;
`
  • TabContent Component ๋‚ด์—์„œ ์‚ฌ์šฉํ•œ TabContentTitle ์ด๋ผ๋Š” Component ๊ฐ€ ๊ถ๊ธˆํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋Š” styled-components ๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด์„œ Component ์— ๋ฐ”๋กœ ์Šคํƒ€์ผ์„ ์ž…ํžŒ ๊ฒƒ์ด๋‹ค.
    (styled-components ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ๊ถ๊ธˆํ•˜๋‹ค๋ฉด ํด๋ฆญ!)
  • ์—ฌ๊ธฐ๊นŒ์ง€๋งŒ ํ•ด๋„ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ์— ์ถฉ์‹คํ•œ ํƒญ์ด ์™„์„ฑ๋œ๋‹ค.

๐Ÿ’œ Tab ์— ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ ๋„ฃ์–ด๋ณด๊ธฐ

๐Ÿค ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ ๋„ฃ๋Š” ์ผ๋ฐ˜์ ์ธ ๋ฐฉ๋ฒ• ์•Œ์•„๋ณด๊ธฐ

  • HTML, CSS ์ž‘์„ฑํ•  ๋•Œ์™€ ๋™์ผํ•˜๊ฒŒ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
    • ๋จผ์ € ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ฃผ๋Š” class ๋ฅผ css ํŒŒ์ผ์— ์ž‘์„ฑํ•œ๋‹ค.
    • Component ์ƒ์„ฑ ๋ฐ ์—…๋ฐ์ดํŠธ๋  ๋•Œ className ์„ ๋ถ™์—ฌ์ค€๋‹ค.

๐Ÿค react-transition-group ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉํ•˜๊ธฐ

1. react-transition-group ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ํ•˜๊ธฐ

  • react-transition-group ์ด๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด๋งŒ ์•Œ๋ฉด css ๋ฅผ ์ž˜ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•˜๋”๋ผ๋„ ๊ฐ„๋‹จํ•œ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋ถ€์—ฌํ•˜๊ธฐ ์‰ฝ๋‹ค.
// npm ์„ ์ด์šฉํ•˜๋Š” ๊ฒฝ์šฐ
npm install react-transition-group

// yarn ์„ ์ด์šฉํ•˜๋Š” ๊ฒฝ์šฐ
yarn add react-transition-group
  • ์ผ๋‹จ ์œ„ ์ฝ”๋“œ ์ค‘ ํ•˜๋‚˜๋ฅผ ํ„ฐ๋ฏธ๋„์— ์ž…๋ ฅํ•˜์—ฌ react-transition-group ์ด๋ผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•ด์ค€๋‹ค.

 

import {CSSTransition} from 'react-transition-group';
  • ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ฃผ๊ณ ์ž ํ•˜๋Š” Component ๊ฐ€ ์žˆ๋Š” ํŒŒ์ผ ์ƒ๋‹จ์— ์œ„์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ CSSTransition ์„ import ํ•ด์ค€๋‹ค.

 

  • react-transition-group ์˜ ์‚ฌ์šฉ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.
    • ๋จผ์ €, <CSSTransition></CSSTransition> ์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ ์šฉํ•  HTML ๋“ค์„ ๊ฐ์‹ธ์ค€๋‹ค. 
    • ๊ทธ๋Ÿฌ๊ณ  ๋‚˜์„œ <CSSTransition> ์— in, classNames, timeout ์†์„ฑ์„ ๋„ฃ์–ด์ค€๋‹ค.

 

2. <CSSTransition></CSSTransition> ์œผ๋กœ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ ์šฉํ•  HTML ๊ฐ์‹ธ์ฃผ๊ธฐ

  <CSSTransition in={onOff} classNames="show" timeout={1000}>
    <TabContent clickedTab={clickedTab}/>
  </CSSTransition>
  • ๋”ฐ๋ผ์„œ ๋‚˜๋Š” TabContent Component ๋ฅผ <CSSTransition></CSSTransition> ์œผ๋กœ ๊ฐ์‹ธ์ฃผ์—ˆ๋‹ค.
    • in ์€ ์Šค์œ„์น˜์— ํ•ด๋‹นํ•˜๋ฉฐ true ์ผ ๋•Œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ ์šฉํ•ด์ค€๋‹ค.
    • classNames ๋Š” ์–ด๋–ค ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ ์šฉํ• ์ง€ ์ด๋ฆ„์„ ์ •ํ•ด์ฃผ๋Š” ๋ถ€๋ถ„์ด๋‹ค.
    • timeout ์€ ํ•ด๋‹น ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ์˜ ์ž‘๋™์‹œ๊ฐ„์„ ์˜๋ฏธํ•œ๋‹ค.

 

3. CSS ํŒŒ์ผ์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ ๋””์ž์ธํ•˜๊ธฐ

.show-enter {
	opacity: 0;
}

.show-enter-active {
	opacity: 1;
	transition: all 1000ms;
}
  • ์ด์ œ css ํŒŒ์ผ(ํ˜น์€ scss ํŒŒ์ผ)์—์„œ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ๋””์ž์ธํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
  • ๋‚˜์˜ ๊ฒฝ์šฐ classNames ๋ฅผ show ๋ผ๊ณ  ์ •ํ•ด์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— .show-enter, .show-enter-active ์™€ ๊ฐ™์ด ํด๋ž˜์Šค๋ช…์„ ์ž‘์„ฑํ•ด์ค€ ํ›„ css ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.
    • -enter ๊ฐ€ ๋ถ™์€ ๊ฒฝ์šฐ Component ์ƒ์„ฑ๋  ๋•Œ ์ ์šฉํ•  CSS ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.
    • -enter-active ๊ฐ€ ๋ถ™์€ ๊ฒฝ์šฐ Component ํ™œ์„ฑํ™”๋˜์–ด์žˆ๋Š” ๋™์•ˆ ์ ์šฉํ•  CSS ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ๋œ๋‹ค.
  • ๋‚˜๋Š” ํˆฌ๋ช…๋„ ์†์„ฑ์ธ opacity ๋ฅผ 0์—์„œ 1์ด ๋  ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.
  • transition ์†์„ฑ์€ ํŠน์ • ์†์„ฑ์„ ํŠน์ • ์‹œ๊ฐ„๋™์•ˆ ์„œ์„œํžˆ ๋ณ€ํ•˜๋„๋ก ๋„์™€์ฃผ๋Š” ์†์„ฑ์ธ๋ฐ, ๋‚˜๋Š” ๋ชจ๋“  ์†์„ฑ์ด 1์ดˆ์˜ ์‹œ๊ฐ„๋™์•ˆ ๋ณ€ํ•˜๊ฒŒ ํ•ด๋‹ฌ๋ผ๊ณ  css ๋ฅผ ์ž‘์„ฑํ–ˆ๋‹ค.

 

4. ํ‰์†Œ์— in={false} ๋กœ ํ•ด๋‘์—ˆ๋‹ค๊ฐ€ ์• ๋‹ˆ๋ฉ”์ด์…˜ ํšจ๊ณผ๋ฅผ ์ ์šฉํ•ด์•ผ ํ•  ๋•Œ true ๋กœ ๋ฐ”๊ฟ”์ฃผ๊ธฐ 

// ์ „์ฒด ์ฝ”๋“œ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
// ์ฝ”๋“œ์˜ ๋‚ด์šฉ์ด ๋„ˆ๋ฌด ๊ธธ์–ด์„œ ๋ถˆํ•„์š”ํ•œ ๋ถ€๋ถ„์€ ์ œ์™ธํ–ˆ๋‹ค.

function Detail(props) {

  let [onOff, setOnOff] = useState(false);

  return (
    <div className="container">

      <Nav className="mt-5" variant="tabs" defaultActiveKey="0">
        <Nav.Item>
          <Nav.Link eventKey="0" onClick={()=>{setOnOff(false); setClickedTab(0)}}>์ƒ์„ธ์ •๋ณด</Nav.Link>
        </Nav.Item>
        <Nav.Item>
          <Nav.Link eventKey="1" onClick={()=>{setOnOff(false); setClickedTab(1)}}>๋ฆฌ๋ทฐ</Nav.Link>
        </Nav.Item>
        <Nav.Item>
          <Nav.Link eventKey="2" onClick={()=>{setOnOff(false); setClickedTab(2)}}>Q&A</Nav.Link>
        </Nav.Item>
      </Nav>

      <CSSTransition in={onOff} classNames="show" timeout={1000}>
        <TabContent clickedTab={clickedTab} setOnOff={setOnOff}/>
      </CSSTransition>

    </div>
  )
}

function TabContent(props) {

  useEffect(()=>{
    props.setOnOff(true);
  })

  if (props.clickedTab === 0){
    return (<TabContentTitle className="mt-5">์ƒ์„ธ์ •๋ณด ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  } else if (props.clickedTab === 1) {
    return (<TabContentTitle  className="mt-5">๋ฆฌ๋ทฐ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  } else if (props.clickedTab === 2) {
    return (<TabContentTitle className="mt-5">Q&A ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  }
}

 

let [onOff, setOnOff] = useState(false);
  • <CSSTransition> ์•ˆ์˜ in ์†์„ฑ์ด ์ƒํ™ฉ์— ๋”ฐ๋ผ true / false ๋กœ ๋ฐ”๋€Œ์–ด์•ผ ํ•˜๋ฏ€๋กœ onOff ๋ผ๋Š” state ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.

 

  <Nav className="mt-5" variant="tabs" defaultActiveKey="0">
    <Nav.Item>
      <Nav.Link eventKey="0" onClick={()=>{setOnOff(false); setClickedTab(0)}}>์ƒ์„ธ์ •๋ณด</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="1" onClick={()=>{setOnOff(false); setClickedTab(1)}}>๋ฆฌ๋ทฐ</Nav.Link>
    </Nav.Item>
    <Nav.Item>
      <Nav.Link eventKey="2" onClick={()=>{setOnOff(false); setClickedTab(2)}}>Q&A</Nav.Link>
    </Nav.Item>
  </Nav>
  • ํŠน์ • ํƒญ์„ ํด๋ฆญํ•ด์„œ ํ•ด๋‹นํ•˜๋Š” TabContent Component ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ onOff state ๋ฅผ true ๋กœ ๋งŒ๋“ค์–ด ์ค„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์—, ์ผ๋‹จ์€ ๊ฐ ํƒญ์„ ๋ˆ„๋ฅด๋ฉด ๋ฌด์กฐ๊ฑด onOff ๋ผ๋Š” state ๊ฐ€ false ๊ฐ€ ๋˜๋„๋ก ๋งŒ๋“ค์–ด์ฃผ์—ˆ๋‹ค.
    (Component ๋กœ๋“œ ์ „์— ๋ชจ๋“  ํƒญ์„ ์•ˆ ๋ณด์ด๊ฒŒ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ณผ์ •์ฒ˜๋Ÿผ ์ƒ๊ฐํ•˜๋ฉด ๋  ๋“ฏํ•˜๋‹ค.)

 

  <CSSTransition in={onOff} classNames="show" timeout={1000}>
    <TabContent clickedTab={clickedTab} setOnOff={setOnOff}/>
  </CSSTransition>
  • TabContent Component ์—์„œ setOnOff() ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฏธ๋ฆฌ setOnOff ๋ผ๋Š” ๋ณ€์ˆ˜๋ช…์œผ๋กœ setOnOff state ๋ฅผ TabContent Component ๋กœ ์ „์†กํ•ด์ฃผ์—ˆ๋‹ค.

 

function TabContent(props) {

  useEffect(()=>{
    props.setOnOff(true);
  })

  if (props.clickedTab === 0){
    return (<TabContentTitle className="mt-5">์ƒ์„ธ์ •๋ณด ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  } else if (props.clickedTab === 1) {
    return (<TabContentTitle  className="mt-5">๋ฆฌ๋ทฐ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  } else if (props.clickedTab === 2) {
    return (<TabContentTitle className="mt-5">Q&A ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.</TabContentTitle>)
  }
}
  • TabContent Component ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ onOff ์˜ state ๋ฅผ ๋ฐ”๊พธ๋ ค๋ฉด useEffect() ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
  • ๊ทธ๋ž˜์„œ, setOnOff ๋ผ๋Š” state ๋ฅผ props ๋กœ ๋ฐ›์•„์ค€ ํ›„์— useEffect() ์•ˆ์— props.setOnOff(true) ๋ผ๊ณ  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์—ฌ, TabContent Component ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ onOff ๊ฐ€ true ๊ฐ€ ๋˜๋„๋ก ํ•ด์ฃผ์—ˆ๋‹ค.

 

728x90
๋ฐ˜์‘ํ˜•