const content = [
{
tab: "Section1",
content: "Content of Section 1"
},
{
tab: "Section2",
content: "Content of Section 2"
}
];
export default function App() {
return (
<div className="App">
<h1>Hello</h1>
{content.map((section) => (
<button key={section.tab}>{section.tab}</button>
))}
</div>
);
}
content 에서 tab의 값을 section.tab으로 호출하여 출력해준다.
tab의 갯수만큼 버튼이 return된다.
const useTabs = (initialTab, allTabs) => {
const [currentIndex, setCurrentIndex] = useState(initialTab);
}
useTabs 에 초기 탭 인덱스와 탭 정보가 담긴 배열 (initialTab, allTabs)의 인자를 받아서
useState(initialTab) 을 작성하여 useState가 항상 initalTab을 갖게 한다
const tabs = useTabs(0, content);
App함수에서 tabs라는 변수를 선언하여 content배열에 담긴 0번 인덱스의 값을 담아준다.
const useTabs = (initialTab, allTabs) => {
const [currentIndex, setCurrentIndex] = useState(initialTab);
if (!allTabs || !Array.isArray(allTabs)){
return;
}
return {
currentItem : allTabs[currentIndex],
}
}
if (!allTabs || !Array.isArray(allTabs)) 에서 배열이 아닐땐 바로 return을 시키고
배열일 경우엔 현재 선택된 탭의 정보와 탭을 변경할 수 있는 함수를 반환.
currentItem(현재 선택된 탭의 정보), changeItem(탭을 변경할 수 있는 함수)
이 함수를 호출하면 해당 인덱스의 탭으로 변경된다.
const {currentItem} = useTabs(0, content);
받아오는 useTabs의 값을 {currentItem}으로 바꿔주고
<div>
{currentItem.content}
</div>
해당 값이 출력 될 수 있게 버튼아랫쪽에 값을 적어준다.
인덱스 0 번의 content 값이 고정으로 출력이 되기 때문에 0 을 index를 바꿔줄 요소가 필요하다
return {
currentItem : allTabs[currentIndex],
changeItem : setCurrentIndex
}
useTabs의 index값을 바꿔줄 changeItem : setCurrentIndex을 return해준다
export default function App() {
const {currentItem, changeItem} = useTabs(0, content);
return (
<div className="App">
<h1>Hello</h1>
{content.map((section, index) => (
<button onClick={()=> changeItem(index)} key={section.tab}>{section.tab}</button>
))}
<div>
{currentItem.content}
</div>
</div>
);
}
{currentItem, changeItem}으로 changeItem 값을 받아준다
이후 버튼의 onClick으로 changeItem을 호출하여 index번호로 값을 받아준다
클릭을 했을 때 setCurrentIndex는 changeItem으로 useState를 업데이트 시켜
currentIndex의 currentItem을 바꿔주어 모든것을 새로고침한다.
const content = [
{
tab: "Section1",
content: "Content of Section 1"
},
{
tab: "Section2",
content: "Content of Section 2"
}
];
const useTabs = (initialTab, allTabs) => {
const [currentIndex, setCurrentIndex] = useState(initialTab);
if (!allTabs || !Array.isArray(allTabs)){
return;
}
return {
currentItem : allTabs[currentIndex],
changeItem : setCurrentIndex
}
}
export default function App() {
const {currentItem, changeItem} = useTabs(0, content);
return (
<div className="App">
<h1>Hello</h1>
{content.map((section, index) => (
<button onClick={()=> changeItem(index)} key={section.tab}>{section.tab}</button>
))}
<div>
{currentItem.content}
</div>
</div>
);
}
전체코드
## 트러블슈팅
const useTabs = (initialTab, allTabs) => {
if (!allTabs || !Array.isArray(allTabs)){
const [currentIndex, setCurrentIndex] = useState(initialTab);
return;
}
return {
currentItem : allTabs[currentIndex],
changeItem : setCurrentIndex
}
}
위 코드를 작성할 때
React Hook "useState" 오류 해결방법
React Hook "useState" is called conditionally. React Hooks must be called in the exact same order in every component render. Did you accidentally call a React Hook after an early return?
const useTabs = (initialTab, allTabs) => {
const [currentIndex, setCurrentIndex] = useState(initialTab);
if (!allTabs || !Array.isArray(allTabs)){
return;
}
return {
currentItem : allTabs[currentIndex],
changeItem : setCurrentIndex
}
}
위와 같은 에러가 떴을 때 아래와 같이 useState()를 최상단으로 이동시켜주시면 된다.
setState >> 모든것을 새로고침 해준다(re-render)
render function이 없어도 render 가능