[React] How React works
[기능 설명]
총 4개의 탭이 있다
'+'를 누르면 1씩 증가, '+++'를 누르면 3씩 증가
'hide details'를 누르면 본문 내용이 보이지 않고
'show details'를 누르면 본문 내용이 보인다
'undo'는 카운트된 숫자를 바로 초기화, 'undo in 2s'는 카운트된 숫자를 2초 후 초기화
const content = [
{
summary: 'React is a library for building UIs',
details:
'Dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
},
{
summary: 'State management is like giving state a home',
details:
'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.',
},
{
summary: 'We can think of props as the component API',
details:
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.',
},
]
탭 할 때마다 보일 content 데이터 리스트
export default function App() {
return (
<div>
<Tabbed content={content} />
</div>
)
}
App 컴포넌트에서 Tabbed 컴포넌트를 렌더링 하고 content를 props로 전달
function Tabbed({ content }) {
const [activeTab, setActiveTab] = useState(0)
return (
<div>
<div className="tabs">
<Tab num={0} activeTab={activeTab} onClick={setActiveTab} />
<Tab num={1} activeTab={activeTab} onClick={setActiveTab} />
<Tab num={2} activeTab={activeTab} onClick={setActiveTab} />
<Tab num={3} activeTab={activeTab} onClick={setActiveTab} />
</div>
{activeTab <= 2 ? (
<TabContent item={content.at(activeTab)} />
) : (
<DifferentContent />
)}
</div>
)
}
Tabbed 컴포넌트에서 activeTab를 사용하여 탭할 때 상태 변화 기록
Tab 컴포넌트에 props로 num, activeTab, setActiveTab 상태 전달
activeTab의 값이 2보다 같거나 작으면 TabContent 컴포넌트를 렌더링 하는데 item이라는 이름으로 prop을 전달하고 전달할 내용은 content.at(activeTab)이다. 여기서 at 메서드는 정숫값을 받아 해당 인덱스에 있는 항목을 반환한다.
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/at
Array.prototype.at() - JavaScript | MDN
Array 인스턴스의 at() 메서드는 정숫값을 받아 해당 인덱스에 있는 항목을 반환하며, 양수와 음수를 사용할 수 있습니다. 음의 정수는 배열의 마지막 항목부터 거슬러 셉니다.
developer.mozilla.org
위의 조건을 만족하지 않으면, DifferentContent 컴포넌트를 렌더링 한다.
function Tab({ num, activeTab, onClick }) {
return (
<button
className={activeTab === num ? 'tab active' : 'tab'}
onClick={() => onClick(num)}
>
Tab {num + 1}
</button>
)
}
Tab 컴포넌트는 다음 탭으로 넘어갈 수 있는 기능을 하는 컴포넌트이다.
버튼을 눌렀을 때, 부모 컴포넌트에서 받아온 num 값을 가지고 버튼 텍스트를 만든다.
function TabContent({ item }) {
const [showDetails, setShowDetails] = useState(true)
const [likes, setLikes] = useState(0)
function handleInc() {
setLikes(likes + 1)
}
function handleTripleInc() {
// 현재 상태에 기반해서 값을 업데이트: 콜백 함수 사용
setLikes(likes => likes + 1)
setLikes(likes => likes + 1)
setLikes(likes => likes + 1)
}
function handleUndo() {
setShowDetails(true)
setLikes(0)
}
function handleUndoLater() {
setTimeout(handleUndo, 2000)
}
return (
<div className="tab-content">
<h4>{item.summary}</h4>
{showDetails && <p>{item.details}</p>}
<div className="tab-actions">
<button onClick={() => setShowDetails(h => !h)}>
{showDetails ? 'Hide' : 'Show'} details
</button>
<div className="hearts-counter">
<span>{likes} ❤️</span>
<button onClick={handleInc}>+</button>
<button onClick={handleTripleInc}>+++</button>
</div>
</div>
<div className="tab-undo">
<button onClick={handleUndo}>Undo</button>
<button onClick={handleUndoLater}>Undo in 2s</button>
</div>
</div>
)
}
TabContent 컴포넌트는 탭 버튼을 눌렀을 때 보여질 내용 박스를 말한다.
showDetails 상태 값이 true일 때 content가 보이고 false일 때는 content가 가려진다.
likes 상태 값은 '+', '+++' 버튼을 눌렀을 때 증가할 수를 나타낸다.
handleInc 함수는 '+' 버튼을 말하는데 1씩 증가한다.
handleTripleInc 함수는 '+++' 버튼이고, 1씩 증가하는 함수를 세 번을 실행시켜 총 3씩 증가하는 것처럼 설정했다. handleInc 함수와 달리 콜백함수를 사용한 이유는 이전 값을 기반으로 값을 업데이트해야 오류가 발생하지 않기 때문이다.
handleUndo 함수는 likes 상태 값을 초기화하는 버튼이다.
handleUndoLater 함수는 2초 뒤 likes 상태 값을 초기화하는 버튼이다.
function DifferentContent() {
return (
<div className="tab-content">
<h4>I'm a DIFFERENT tab, so I reset state 💣💥</h4>
</div>
)
}
DiffentContent 컴포넌트는 'activeTab의 값이 2보다 같거나 작으면' 이라는 조건을 만족하지 못했을 때 보이는 컴포넌트이다.