ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Week02 리액트/Next.js 기초 3.5 React Hooks (1) - 상태 훅
    웹개발/React 2023. 12. 31. 16:39

    React Hooks는 훅(Hook)을 통해 함수 컴포넌트 안의 상태나 라이프 사이클을 다루기 위한 기능이다.

    잘 와닿지 않는데 HTML과 Vanila JS를 사용 할 줄 안다는 가정하에 훅이 무슨 역할인지 이해해보자.

     

    유저가 input을 입력하고 submit버튼을 누르면 유저의 입력값이 나타나는 코드를 작성한다고 가정해보자.

    Java script 파일에 작성해야 할 점을 생각해본다면 3가지로 추릴 수 있다.

    1. submit버튼 클릭시 input에 들어와 있는 값을 가져와야한다.

    2. submit버튼에 클릭 시 어떤 행동을 하라는 (이 경우에는 input값을 가져와 입력값을 출력하는) 이벤트 리스너를 달아야 한다.

    3. input값에 들어가 있던 값을 어느 엘리먼트에서 프린트 할 것인지 가져와야 한다.

    따라서 document.getElement method를 사용해 여러가지 엘리먼트의 값들을 끌어와야 하고 엘리먼트들이 많아지고 복잡해질 수록 id, class등 관리가 어려워 질 것이다.

     

    React에서는 html 사이에 코드 (변수, 함수) 등을 그대로 넣을 수 있기 때문에 2, 3번은 손쉽게 해결된다. 다만 1, 2번이 문제인데 1번은 상태를 관리하는 useState를 사용한다면 유저가 입력값을 변경할때마다 실시간으로 변경되며 변수에 저장할 수 있다. (useState)

    import React, { useState } from 'react';
    
    const App = () => {
      const [result, setResult] = useState('');
    
      const handleSubmit = (event) => {
        event.preventDefault();
        const inputValue = event.target.inputField.value;
        setResult(inputValue);
      };
    
      return (
        <div>
          <form onSubmit={handleSubmit}>
            <label htmlFor="inputField">Enter your text:</label>
            <input type="text" id="inputField" name="inputField" required />
            <button type="submit">Submit</button>
          </form>
          {result && <div>{`You entered: ${result}`}</div>}
        </div>
      );
    };
    
    export default App;

    코드가 이해가 잘 되지 않을 수 있는데 사용된 useState에 대해 설명하고 다시 설명하도록 하겠다.

     

    3.5.1 useState와 useReducer - 상태 훅

    "상태" 훅이다. 변수나 Object의 상태 변화를 다룬다. 이때 상태변화란 ? 기본형인 숫자를 예로 들자면 count라는 이름의 변수의 value가 1일 때 우리는 이 변수의 상태를 1이라고한다. count에 1을 더한다면 count=count+1이 되고 이 변화를 상태 변화라한다. 복잡한 경우라면 Object형이 있다. 이름, 전화번호, 주소 등등이 담겨있는 객체에서 특정 값을 변경 시킨다면 이 또한 상태 변화라고 한다.

    useState와 useReducer의 큰 차이점을 꼽자면 자료형에 구애받지 않고 다양한 상태변화를 작성할 수 있는가이다. 

    ( 상태 변화 함수를 사용해 상수, 정해진 값으로 바꾸는건 논외로 치자. ex) state값을 1로 변경, "hello"로 변경 )

    useState와 useReducer에 대해 알아보며 위의 문장을 이해해보자.

     

    3.5.1 - 1 useState

    const [상태변수이름, 업데이트함수이름] = useState(상태 변수의 초깃값)

    counter라는 이름을 가진 변수에 초깃값은 0을 주고 어떤 조건 마다 counter+1을 해줘야 한다면.

    const [counter,  ] =useState(0) 이라고 작성할 수 있다. 업데이트할 함수의 이름은 맘대로 정하는데 일반적으로 set+변수이름으로 정한다. (웹개발이니까 카멜케이스로 쓰자.)

    따라서 이렇게 작성할 수 있다.

    import { useState } from 'react'
    const [counter, setCounter] = useState(0);

    업데이트 함수를 호출 할 때는 인수에 값을 전달하는 방법과 함수를 전달하는 방법이 있다.

    1. 값을 전달할 경우
      • setCounter(1), setCounter("hello"), setCounter(true) 등 상수 전달
      • setCounter(counter+1) 과 같이 counter 변수를 가져와 현재 값을 기준으로 변한 값 전달
      • 따라서 이 경우 함수의 인수에 들어간 값 자체가 counter의 값이 된다.
    2. 함수를 전달 할 경우
      • setCounter((prevCounter)=>prevCounter+1)
      • 들어가는 함수의 기본인자에는 기존의 counter값이 들어간다. 그리고 이 함수가 return하는 값이 counter의 상태가된다.

    따라서 setCounter(counter+1) 과 setCounter((prevCounter) => prevCounter+1))은 같다.


    import React, { useState } from 'react';
    
    const App = () => {
      const [result, setResult] = useState('');
    
      const handleSubmit = (event) => {
        event.preventDefault();
        const inputValue = event.target.inputField.value;
        setResult(inputValue);
      };
    
      return (
        <div>
          <form onSubmit={handleSubmit}>
            <label htmlFor="inputField">Enter your text:</label>
            <input type="text" id="inputField" name="inputField" required />
            <button type="submit">Submit</button>
          </form>
          {result && <div>{`You entered: ${result}`}</div>}
        </div>
      );
    };
    
    export default App;

    이제 이 코드를 다시 보면 조금 이해가 새로 될 것이다. useState를 사용해 input filed에 있는 value값을 받아오고 상태를 변경해주면 이후에 <form> 뒤의 result 에서 입력 받은 값을 사용 할 수 있다.

     

    3.5.1 - 2 useReducer

    reducer는 현재 상태와 들어오는 action을 기반으로 다음 상태를 결정한다.

    사용법을 보자.

    const reducer = (현재 상태 변수 , action) => {
    	if(action=='something') return 다음 상태;
        else return 다음 상태;
    }
    
    const [현재 상태 변수, dispatch] = useReducer(reducer, 초기 상태);

    앞서 작성했던 counter+1을 useReducer로 작성해보자.

    import { useReducer } from 'react'
    
    type Action = 'INCREMENT' | 'RESET'
    
    const reducer = (currentCounter: number, action: Action) => {
    	if (action === 'INCREMENT') return currentCounter+1;
        else return 0;
    }
    
    const Counter = () => {
    	const [ count, dispatch ] = useReducer(reducer, 0);
        return {
        <>
        	<p> Count : {count}</p>
            <button onClick={()=>dispatch('INCREMENT')}>+</button>
            <button onClick={()=>dispatch('RESET')}>Reset</button>
        </>
        }
    }
    
    export default Counter;

    Increment reset을 다 useState로 구현하려면 setState자체에 다 달라지는 값들을 넣어줘야 하고 이 경우 코드의 볼륨이 커지면 이해하기 힘들게 된다. 하지만 Reducer를 사용하면 다양한 Action을 다루면서도 한 reducer안에서 관리할 수 있기 때문에 코드의 유지,보수가 쉬워지는 장점이 있다.

     

    혹시 틀린 부분이 있다면 지적해주시면 감사하겠습니다. :)

     

    '웹개발 > React' 카테고리의 다른 글

    Week01 리액트/Next.js 기초 3.1-3.4  (0) 2023.12.31
    React study 시작  (0) 2023.12.31

    댓글

Designed by Tistory.