티스토리 뷰

리액트 스터디

[React] 6. 리액트 스터디 - State

더밸류(THEVALUE) 2022. 12. 29. 17:02

[ State ] - useState Hook

컴포넌트의 내부에서 변경 가능한 데이터를 관리할 때 사용

값을 저장하거나 변경할 수 있는 객체로 보통 이벤트와 함께 사용되는데 

예제를 보면 다음과 같다.

 

React.useState는 배열 형태의 객체를 반환
첫번째 요소는 변경될 값을 관리할 변수  - counter
두번째 요소는 이벤트 처리를 위한 함수  - setCounter

counter 이름의 변수에 0으로 초기화한 데이터를 저장하고
setCounter 이름의 함수를 통해 
값을 변경하면서 화면에 값을 리렌더링(다시 그리기) 하는 과정을 거침

 

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- 1. 라이브러리 (CDN)  -->
<script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
<!-- Load Babel -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

<title>리액트 스터디중</title>
</head>
<body>
  <!-- 2. 출력 영역 지정  -->
  <div id="display"></div>
  
  <!-- 3. 화면에 출력될 내용 -->
  <script type="text/babel">
    const root = document.getElementById("display");
   
    function App() {
      const [counter, setCounter] = React.useState(0);
      const onClick = () => {
       // 1. 값으로 counter 값 + 1 을 전달
       // setCounter(counter + 1);
       // 2. 함수 형태로 전달 : 여러 곳에서의 업데이트 (카운트 증가) 시 현재 값을 제대로 갖고 +1을 처리함
       // setCounter((current) => current + 1);
      }
      
      return (
        <div>
          <h3>Total Clicks: {counter}</h3>
          <button onClick={onClick}>Click me</button>
        </div>
      )
    }
    ReactDOM.render(<App />, root);
  </script>
</body>
</html>

 

특정 값에 대한 state 관리를 통해 
화면에 변경되는 이벤트를 처리
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <!-- 1. 라이브러리 (CDN)  -->
  <script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
  <!-- Load Babel -->
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

  <title>리액트 스터디중</title>
</head>

<body>
  <!-- 2. 출력 영역 지정  -->
  <div id="display"></div>

  <!-- 3. 화면에 출력될 내용 -->
  <script type="text/babel">
    const root = document.getElementById("display");

    function App() {
      const [amount, setAmount] = React.useState(0);
      const [inverted, setInverted] = React.useState(false);
      const onChange = (event) => {
        setAmount(event.target.value);
      }
      const reset = () => setAmount(0);
      const onInverted = () => {
        reset();
        setInverted((current) => !current);
      }
      return (
        <div>
          <h1>Super Converter</h1>

          <div>
            <label htmlFor="minutes">Minutes</label>
            <input
              value={inverted ? amount * 60 : amount}
              id="minutes"
              placeholder="Minutes"
              type="number"
              onChange={onChange}
              disabled={inverted}
            />
          </div>

          <div>
            <label htmlFor="hours">Hours</label>
            <input 
              value={inverted ? amount : Math.round(amount / 60)} 
              id="hours" 
              placeholder="Hours" 
              type="number"
              onChange={onChange}
              disabled={!inverted} />
          </div>
          <button onClick={reset}>reset</button>
          <button onClick={onInverted}>{inverted ? "Turn back" : "Invert"}</button>
        </div>
      )
    }
    ReactDOM.render(<App />, root);
  </script>
</body>

</html>

 

여러개의 컴포넌트를 결합하여 화면에 리랜더링하는 예제
{} 안의 삼항연산자를 통해 셀렉트박스에서 선택한 index 를 체크하여 
보여줄 컴포넌트를 지정하고 있다.
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <!-- 1. 라이브러리 (CDN)  -->
  <script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
  <!-- Load Babel -->
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

  <title>리액트 스터디중</title>
</head>

<body>
  <!-- 2. 출력 영역 지정  -->
  <div id="display"></div>

  <!-- 3. 화면에 출력될 내용 -->
  <script type="text/babel">
    const root = document.getElementById("display");

    function MinutesToHours() {
      const [amount, setAmount] = React.useState(0);
      const [inverted, setInverted] = React.useState(false);
      const onChange = (event) => {
        setAmount(event.target.value);
      }
      const reset = () => setAmount(0);
      const onInverted = () => {
        reset();
        setInverted((current) => !current);
      }
      return (
        <div>
          <div>
            <label htmlFor="minutes">Minutes</label>
            <input
              value={inverted ? amount * 60 : amount}
              id="minutes"
              placeholder="Minutes"
              type="number"
              onChange={onChange}
              disabled={inverted}
            />
          </div>

          <div>
            <label htmlFor="hours">Hours</label>
            <input 
              value={inverted ? amount : Math.round(amount / 60)} 
              id="hours" 
              placeholder="Hours" 
              type="number"
              onChange={onChange}
              disabled={!inverted} />
          </div>
          <button onClick={reset}>reset</button>
          <button onClick={onInverted}>{inverted ? "Turn back" : "Invert"}</button>
        </div>
      )
    }

    function KmToMiles() {
      return <h3>KM 2 M</h3>;
    }

    function App() {
      const [index, setIndex] = React.useState("xx");
      const onSelect = (event) => {
        console.log(event.target.value);
        setIndex(event.target.value);
      }

      console.log('render w/', index);

      return (
        <div>
          <h1>Super Converter</h1>
          <select value={index} onChange={onSelect}>
            <option value="xx">Select your units</option>
            <option value="0">Minutes & Hours</option>
            <option value="1">Km & Miles</option>  
          </select>
          <hr />
          {index === "xx" ? "please select your units" : null}
          {index === "0" ? <MinutesToHours /> : null}
          {index === "1" ? <KmToMiles /> : null}
        </div>
      )
    }
    ReactDOM.render(<App />, root);
  </script>
</body>

</html>