먼저 버튼 두개를 만드는 탭을 구성 해봅시다.

import React, { useState } from "react";
import ReactDOM from "react-dom";

const content = [
  {
    tab: "Section 1",
    content: "I'm the content of the Section 1"
  },
  {
    tab: "Section 2",
    content: "I'm the content of the Section 2"
  }
];

const App = () => {
  return (
    <div>
      {content.map(section => (
        <button>{section.tab}</button>
      ))}
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

 

 

여기서 노마드는 물어봅니다.

모두가 아닌 내가 원하는 콘텐츠만 띄워주는건 어떻게 구성하면 간편하고 쌈빡할까?

 

바로 이런식으로 합니다.

 

import React, { useState } from "react";
import ReactDOM from "react-dom";

const content = [
  {
    tab: "Section 1",
    content: "I'm the content of the Section 1"
  },
  {
    tab: "Section 2",
    content: "I'm the content of the Section 2"
  }
];

const useTabs = (initialTab, allTabs) => {
  if (!allTabs || !Array.isArray(allTabs)) {
    return;
  }
  const [currentIndex, setCurrentIndex] = useState(initialTab);
  return {
    currentItem: allTabs[currentIndex]
  };
};

const App = () => {
  const { currentItem } = useTabs(0, content);
  return (
    <div>
      {content.map(section => (
        <button>{section.tab}</button>
      ))}
      <div>{currentItem.content}</div>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

 

이렇게 하면 App부분에서 useTabs 할때 파라미터 인덱스 값만 바꾸어주면 왔다갔다 됩니다.

이걸 자동화 해봅시다.

 

import React, { useState } from "react";
import ReactDOM from "react-dom";

const content = [
  {
    tab: "Section 1",
    content: "I'm the content of the Section 1"
  },
  {
    tab: "Section 2",
    content: "I'm the content of the Section 2"
  }
];

const useTabs = (initialTab, allTabs) => {
  if (!allTabs || !Array.isArray(allTabs)) {
    return;
  }
  const [currentIndex, setCurrentIndex] = useState(initialTab);
  return {
    currentItem: allTabs[currentIndex],
    changeItem: setCurrentIndex
  };
};

const App = () => {
  const { currentItem, changeItem } = useTabs(0, content);
  return (
    <div>
      {content.map((section, index) => (
        <button onClick={() => changeItem(index)}>{section.tab}</button>
      ))}
      <div>{currentItem.content}</div>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

 

Hooks 사용이 미숙해 이해를 못하겠더군요.. 초보코더라

해석해보니..

useTabs에서 리턴값을 오브젝트로 두가지 넘겨주기에 오브젝트로 두가지 받을 수 있게 구성해두고,

받았을때 버튼이 생성됩니다. 콘텐츠와 함께요. 그리고 map함수에서 index의 값을 사용하여 버튼 onClick시

changeItem을 실행하게 되고, 위 changeItem은 내부에 보시면 인덱스값이 다르게 들어가 currentIndex가 다르게 들어가게 되고, (스테이트 값의 변동) currentIndex 스테이트값이 바뀌면 currentItem의 값이 기존에 만들때 allTabs[0]에서 allTabs[1]로 바뀌게 됩니다.그러면 div 제일 하단에 {currentItem.content}로 출력하던 부분에서 currentItem이 [1]로 바뀌었기에 content 1번을 출력하게 되는 구조입니다.

 

말이 되게 어려운데 제대로 이해하시려면 한번 흐름을 뜯어먹어 보시기 바랍니다.

버튼클릭 - changeItem(버튼index)실행 - currentIndex스테이트 값 변경 - 재랜더링 - App시작 시 0번을 넘겼지만 currentIndex는 이미 변경됐으므로 리턴에서 currentItem은 allTabs[index]를 리턴하여 바뀌게 됨.

 

쉬운 예시가 아래에 있습니다.

 

import React, { useState } from "react";
import ReactDOM from "react-dom";


const StateTest = (index) => {
  console.log("index: ",index)
  const [t1, setT1] = useState(index);
  console.log("State: ",t1)
  return {
    currentItem: t1,
    changeItem: setT1
  };
}

const App = () => {
  const {currentItem, changeItem} = StateTest(0)

  return (
    <div>
      <h1>{currentItem}</h1>
      <button onClick={() => changeItem(0)}>0</button>
      <button onClick={() => changeItem(1)}>1</button>
      <button onClick={() => changeItem(2)}>2</button>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

콘솔

위 예제와 비슷한 예시입니다. 콘솔을 보시면 아시겠지만, State의 변동이 일어나서 재 랜더링 할때에도 여전히 App 최상단에 StateTest(0)이 있기에 index는 콘솔로 0이 계속 찍히게 됩니다. 하지만 State의 값은 변동이 있죠.

 

처음 하면서 헷갈린게 함수안에 const [t1, setT1] = useState(index) 라고 되어있어, 재 랜더링 하고 함수를 들어갈때마다 index값의 변동이 없기에 무조건 0으로 초기화될줄 알았는데, setT1을 함수로 changeItem에 전달했고, 그걸 통하면 changeItem(param)을 하면 스테이트 값만 쏙 바뀌더라구요? 완전 논리적으로 파고드는 스타일이 아닌지라 그런 이유까진 정확히 모르겠습니다만,,, 이렇게 알고 넘어가려구요

+ Recent posts