Posts [React] 리액트 Hooks (2) - useReducer
Post
Cancel

[React] 리액트 Hooks (2) - useReducer


리액트 Hooks(2) - useReducer


  • 🚩 useReducer

함수형 컴포넌트에서 현재 상태, 그리고 업데이트를 위한 정보를 담은 action 값을 전달받고 새로운 상태를 반환하는 함수


☝ 1 | useReducer 함수의 기본적인 사용 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import React, {useReducer} from 'react';

function reducer(state, action){
  //action의 타입에 따른 작업 수행
  switch(action.type){
    case 'INCREMENT':
      return { value: state.value + 1 };
    case 'DECREMENT':
      return { value: state.value - 1 };
    default:
      return state;
  }
}

const Counter = () => {
  const [state, dispatch] = useReducer(reducer, {value : 0})
  return (
    <div>
      <p>
        현재 카운터 값 <b>{state.value}</b>
      </p>
      <button onClick={()=>dispatch({type:'INCREMENT'})}>+1</button>
      <button onClick={()=>dispatch({type:'DECREMENT'})}>-1</button>
    </div>
  );
};

export default Counter;
  • useReducer 함수는 첫 번째 인자에 리듀서 함수를 넣습니다. 두 번째 인자에는 리듀서의 기본 값을 넣습니다.
  • const [state, dispatch] = useReducer(reducer, {value : 0}) 이 부분에서 state는 현재 가리키는 것의 상태(여기서는 value)를, dispatch는 액션을 발생시키는 함수를 정의한 것입니다.
  • button onClick 부분을 보면 dispatch 함수 내에 액션 값을 넣어 주면서, reducer 함수가 호출됩니다.
  • 이처럼 컴포넌트 업데이트 로직(reducer 함수가 맡은 부분)을 컴포넌트 바깥으로 빼낼 수 있게 됩니다.

☝ 2 | useReducer 함수로 인풋 상태 관리

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import React, { useReducer } from 'react';

function reducer(state, action){
  return {
    ...state, // state 값을 여기에 복사하고,
    [action.name]: action.value // 값을 덮어씌운다.
  };
}

const Info = () => {
  const [state, dispatch] = useReducer(reducer, {
    name: '',
    nickname: ''
  });
  
  const {name, nickname} = state;

  const onChange = e =>{
    dispatch(e.target);
  }

  return (
    <div>
      <div>
        <input name = "name" value={name} onChange={onChange}/>
        <input name = "nickname" value={nickname} onChange={onChange}/>
      </div>
      <div>
        <div>
          이름 : {name}
        </div>
        <div>
          닉네임 : {nickname}
        </div>
      </div>
    </div>
  );
};

export default Info;
  • useReducer에서 state를 name, nickname으로 정의하였습니다.
  • const {name, nickname} = state 이 부분을 통해, 위에서 정의한 state 값이 각각 name, nickname에 들어갔습니다. - 🎁 객체 비구조화 할당 문법
  • 쉽게 말해 useReucer의 첫 번째 인자에 들어간 리듀서 함수는, useState에서 state를 변경하는 함수와 하는 역할이 비슷하다고 생각하면 됩니다.
    • 단, useState 에서 state를 변경하는 함수는 그 state 값을 그대로 사용하지만, useReducer 에서 state를 변경하는 reducer 함수는 추가적으로 가공하여 새로운 상태를 반환하는 것에서 그 내용의 차이가 있습니다.
  • 이제 reducer 함수를 정의한 부분을 보겠습니다.
    • [action.name] : action.value
      • onChange 함수에서 reducer 함수를 호출한 부분을 확인해 보면 action 값을 e.target 으로 지정했으므로, action.name 은 e.target.name 과 같고, action.value는 e.target.value와 같습니다.
      • e.target.name 여기에선 해당 input의 name의 값을 말합니다.
      • e.target.value는 input의 value 값을 말합니다.
      • 이로써 state의 값을 value 로 변경할 수 있게 됩니다.

  • useReducer 함수의 액션은 어떤 값도 사용이 가능합니다. 즉, 인자로 액션 값을 넣는 dispatch 함수e.target 를 액션 값으로 넣었습니다. 이벤트 객체가 지니고 있는 e.target 값 자체를 넣은 것입니다.

  • input 이 여러개였을 경우 기존에는 useState를 여러번 사용했고, 각각 다른 state setter 함수도 여러 개가 만들어지게 됩니다. 따라서 그에 따른 onChange 핸들링 함수도 여러 개 존재했었습니다.

    • [예] name, nickname state를 정의하고 setName, setNickname 이라는 함수도 정의함

    • 1
      2
      3
      4
      5
      6
      7
      8
      9
      
      const [name, setName] = useState('');
      const [nickname, setNickname] = useState('');
          
      const onChangeName = e => {
          setName(e.target.value);
      };
      const onChangeNickname = e => {
          setNickname(e.target.value);
      }
      
  • 그러나 useReducer를 사용함으로써 인풋의 갯수가 계속 많아지더라도 useState를 여러 번 사용할 필요가 없이 코드를 간결하게 유지할 수 있습니다.


이 포스팅은 리액트를 다루는 기술(저자 김민준)을 학습하는 과정에서 개인적으로 정리한 내용입니다.

[운영체제] 운영체제란 무엇일까

[GraphQL] GraphQL이란 무엇일까? (Over/Underfetching 문제 해결)