React Hooks (useReducer, useMemo)

Yubin·2022년 2월 1일
0

useReducer

useReducer는 useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값을 업데이트해 주고 싶을 때 사용하는 Hook이다. 리듀서라는 개념은 나중에 글에서 리덕스를 배울 때 더 자세히 알아보겠다.

리듀서는 현재 상태, 그리고 업데이트를 위해 필요한 정보를 담은 액션(actiom) 값을 전달받아 새로운 상태를 변환하는 함수이다. 리듀서 함수에서 새로운 상태를 만들 때는 반드시 불변성을 지켜 주어야한다.

function reducer(state, action) {
    return(...);
}

액션 값은 주로 다음과 같은 형태로 이루어져 있다.

  type: 'INCREMENT',
 // 다른 값들이 필요하다면 추가로 들어감

나중에 다룰 리덕스에서 사용하는 액션 객체에는 어떤 액션인지 알려 주는 type 필드가 꼭 있어야 하지만, useReducer에서 사용하는 액션 객체는 반드시 type을 지니고 있을 필요가 없다.
심지어 객체가 아니라 문자열이나 숫자여도 상관없다.

카운터 구현하기

먼저 useReducer를 사용하여 기존의 Counter 컴포넌트를 다시 구현해보자.

import { useReducer } from "react"

function reducer(state, action) {
   switch (action.type) {
       case 'INCREMENT':
           return { value: state.value + 1 };
       case 'DECREMENT':
           return { value: state.value - 1 };
       default:
           return state;
   }
}

const Hooks = () => {
   const [state, dispatch] = useReducer(reducer, { value: 0 });

   return (
       <div>
           <h2>현제 카운터 값은{state.value} 입니다</h2>

           <button onClick={() => {
               dispatch({ type: 'INCREMENT' })
           }}>+1</button>

           <button onClick={() => {
               dispatch({ type: 'DECREMENT' })
           }}>-1</button>
       </div>
   )
}
export default Hooks

useReducer의 첫 번째 파라미터에는 리듀서 함수를 넣고, 두 번째 파라미터에는 해당 리듀서의 기본값을 넣어 준다. 이 Hook을 사용하면 state값과 dispatch함수를 받아온다. 여기서 state는 현재 가리키고 있는 상태고, dispatch는 액션을 발생시키는 함수다. dispatch(action) 과 같은 형태로, 함수 안에 파라미터로 액션 값을 넣어 주면 리듀서 함수가 호출되는 구조다.

useReducer를 사용했을 때의 가장 큰 장점은 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼 수 있다는 것이다.

인풋 상태 관리하기

이번에는 useReducer를 사용하여 컴포넌트에서 인풋 상태를 관리해 보겠다. 기존에는 인풋이 여러 개 여서 useState를 여러 번 사용 했지만, useReducer를 사용하면 기존에 클래스형 컴포넌트에서 input태그에 name값을 할당하고 e.target.name을 참조하여 setState를 해 준 것과 유사한 방식으로 작업을 처리할 수 있다.

import { useReducer } from "react";

function reducer(state, action) {
    return {
        ...state,
        [action.name]: action.value
    }
}
const Hooks = () => {
    const [state, dispatch] = useReducer(reducer, {
        name: '',
        nickname: '',
    });
    const { name, nickname } = state;
    const onChange = e => {
        dispatch(e.target)
    }

    return (
        <div>
            <div>
                <input type="text"
                    name="name"
                    value={name}
                    onChange={onChange}
                />

                <input type="text"
                    name="nickname"
                    value={nickname}
                    onChange={onChange}
                />
            </div>
            <div>
                이름 : {name}
            </div>
            <div>
                닉네임 : {nickname}
            </div>
        </div>

    )
}
export default Hooks

useReducer에서의 액션은 그 어떤 값도 사용 가능하다. 그래서 이번에는 이벤트 객체가 지니고 있는 e.target 값 자체를 액션 값으로 사용했다. 이런 식으로 인풋을 관리하면 아무리 인풋의 개수가 많아져도 코드를 짧고 깔끔하게 유지할 수 있다.

profile
꾸준히 기록하는 개발자가 꿈인 고등학생

0개의 댓글