useState를 쓰면서 배우기 쓰면서 배우기 (React Hooks 입문 시리즈 4/6)

로드맵



React 16.8에서 추가된 기능인 React Hooks에 대해 썼습니다.

쓰면서 배우는 React Hooks 입문 시리즈로 새로 작성했습니다.
  • React.memo/useCallback/useMemo
  • Context/useContext
  • useRef

  • useState 이번
  • useEffect
  • useReducer

  • 소개



    React의 내장 훅인 useState 의 설명을 합니다.

    useState란?



    state 와 state 의 갱신 함수를 돌려주는 후크입니다.

    이 후크를 이용하면 컴포넌트 내에서 상태 관리가 가능합니다.

    state 가 갱신되면(자) 컴퍼넌트는 재렌더링 됩니다.

    구문


    const [state, setState] = useState(state初期値)
    

    활용 예... 카운트 앱



    샘플 코드

    App.js
    import React, { useState } from "react";
    
    const App = () => {
      const [count, setCount] = useState(0);
    
      const increment = () => setCount(count + 1);
    
      return (
        <div className="App">
          <p>{count}</p>
          <button onClick={increment}>+1</button>
        </div>
      );
    };
    
    export default App;
    



    활용 예 ... 카운트 앱 (setState의 업데이트 함수 인수에 함수를 전달하는 버전)



    샘플 코드

    App.js
    import React, { useState } from "react";
    
    const App = () => {
      const [count, setCount] = useState(0);
    
      const increment = () => setCount((currentCount) => currentCount + 1);
    
      return (
        <div className="App">
          <p>{count}</p>
          <button onClick={increment}>+1</button>
        </div>
      );
    };
    
    export default App;
    



    이것의 무엇이 기쁜가? => 로직을 구성 요소 밖으로 잘라낼 수 있습니다.

    이렇게하면 논리가 외부에 의존하기 어렵습니다. 또, 공통화하기 쉬워지는 이점도 있습니다.

    샘플 코드(setState의 인수에 건네준 함수를 외부화)

    App.js
    import React, { useState } from "react";
    
    const App = () => {
      const [count, setCount] = useState(0);
    
      const increment = () => setCount((currentCount) => currentCount + 1);
    
      return (
        <div className="App">
          <p>{count}</p>
          <button onClick={increment}>+1</button>
        </div>
      );
    };
    
    export default App;
    

    처음에 쓴 setState 인수라면 setState(count + 1) 그렇다면 외부로 잘라낼 수 없지만

    setState의 갱신 함수의 인수에 함수를 건네주는 버젼이면, 컴퍼넌트 밖으로 잘라낼 수 있습니다.

    App.js
    import React, { useState } from "react";
    
    // setState内のロジックを外部化
    const updateCount = (currentCount) => currentCount + 1;
    
    const App = () => {
      const [count, setCount] = useState(0);
    
      const increment = () => setCount(updateCount);
    
      return (
        <div className="App">
          <p>{count}</p>
          <button onClick={increment}>+1</button>
        </div>
      );
    };
    
    export default App;
    



    활용 예... 객체를 어떻게 다루는가?



    책의 정보를 다루는 object 를 state 로 표시해 봅시다.

    샘플 코드

    App.js
    import React, { useState } from "react";
    
    const bookInfo = {
      title: "サピエンス全史",
      author: "ユヴァル・ノア・ハラリ",
      price: 2000
    };
    
    const App = () => {
      const [book, setBook] = useState(bookInfo);
    
      // 値が更新される関数
      const updateBookInfo = () => setBook({ ...book, price: book.price + 1 });
    
      // 値が更新されない関数
      const updateBookInfo2 = () => {
        book.price = book.price = 1;
        setBook(book);
      };
    
      return (
        <div className="App">
          <p>{book.title}</p>
          <p>{book.author}</p>
          <p>{book.price}</p>
          <button onClick={updateBookInfo}>update</button>
        </div>
      );
    };
    
    export default App;
    



    만약 ...book, 를 지워버리고 함수 updateBookInfo
    const updateBookInfo = () => setBook({ price: book.price + 1 });
    

    setState 갱신 후의 값은, {price: 2001} (와)과, price 만이 될 것입니다. 이것은 setState가 차이만 병합이 아니라 대체이기 때문입니다.

    주의점



    버튼 클릭시 함수
  • 함수가 updateBookInfo이면 값이 업데이트됩니다
  • 함수를 updateBookInfo2로 설정하면 값이 업데이트되지 않습니다

  • 원인은 updateBookInfo2 에 건네받은 book 가 변경전과 같은 것으로 간주되었기 때문입니다.

    React 의 state 는 Object.is() 로 변경의 유무를 판정하고 있는 것 같습니다.
  • Object.is()가 true이면 동일 (변경하지 않음)으로 간주하고 React이면 구성 요소가 다시 렌더링되지 않습니다.
  • Object.is()가 false이면 변경된 것으로 간주하고 React이면 구성 요소가 다시 렌더링됩니다.
  • 하지만 state의 내용은 갱신됩니다. 컴포넌트가 다시 렌더링되지 않기 때문에 사용자의 눈에는 변하지 않는 것처럼 보입니다.



  • Object.is 에 관해서는, 이하가 참고가 되었습니다.

    반면에 updateBookInfo 함수는 스프레드 연산자를 사용하여 새 객체를 생성하므로 Object.is()의 결과는 false가되고 구성 요소가 다시 렌더링됩니다.

    이것은, setState 함수가 배열의 경우에서도 같습니다.

    이번은 이상입니다.

    참고

    좋은 웹페이지 즐겨찾기