All Articles

리듀서와 useReducer

리액트에서 상태값을 변경하는 2가지 방법

  1. setter 함수를 직접 제공
  2. setter 함수를 제공하지 않고 dispatch 함수를 제공 - Redux 방식

dispatch 함수 이용 예

dispatch({ 액션 객체 }) 형태로 작성한다.

dispatch({ type: "INCREMENT", payload: 1 })

액션 객체에는 type이라는 키가 필수로 포함되어야 한다. type 키 값으로는 해당 dispatch 함수의 type을 문자열로 명시한다.

type을 제외하고 나머지는 자유롭게 값 지정 가능하나, 보통 payload 키를 넣어 type에 대한 값을 지정한다.

위 예시에서 type: "INCREMENT"payload: 1이라는 것은 상태값을 1씩 증가시키겠다는 의미다.

useReducer 훅

useReducer 훅을 이용해 컴포넌트 상태값을 리덕스의 리듀스처럼 관리할 수 있다.

(참고 - 리듀서란 dispatch 함수로부터 액션 객체를 받아서 상태값에 대한 setter 로직을 구현한 함수를 말한다.)

먼저 리듀서를 사용하지 않은 예시다. input 란에 값을 입력하면 myname, age 상태값에 바로 반영하는 로직이다.

const App = () => {
  const [person, setPerson] = useState({ myname: '', age: '' });
  const { myname, age } = person;
  return (
    <div>
      myname: {myname}, age: {age}
      <br />
      <input
        type="text"
        placeholder="name"
        onChange={(e) => setPerson({age, myname: e.target.value})} />
      <input
        type="text"
        placeholder="age"
        onChange={(e) => setPerson({myname, age: e.target.value})} />
    </div>
    // e.target에서 target이란 현재 element를 나타내고,
    // e.target.value는 현재값을 나타냄
  );
};

export default App;

useReducer 훅을 사용한다면 이렇게 바꿀 수 있다.

const reducer = (prevState, action) => {
  // type을 받아와서
  const { type, value } = action;
  // type에 따라
  if ( type === 'SET_NAME' ) {
    // 적절히 상태값 세팅
    return { ...prevState, myname: value };
  }
  else if (type === 'SET_AGE') {
    return { ...prevState, age: value };
  }
  return prevState;
};

const App = () => {
  const [state, dispatch] = useReducer(reducer, { myame: '', age: '' });
  const { myname, age } = state;
  const onChange = (e) => {
    const { name: type, value } = e.target;
    dispatch({ type, value });
  };
  return (
    <div>
      myname: {myname}, age: {age}
      <br />
    <input
        type="text"
        name="SET_NAME"
        placeholder="name"
        onChange={onChange} />
      <input
        type="text"
        name="SET_AGE"
        placeholder="age"
        onChange={onChange} />
    </div>
  );
};

export default App;