리액트/Hooks

ch03.useReducer

webmaster 2021. 11. 15. 10:26
728x90
  • 현재 상태, 업데이트를 위해 필요한 정보를 담은 액션 값을 전달받아 새로운 상태로 반환하는 함수
  • 새로운 상태는 항상 불변성을 지켜야 된다.
  • function reducer(state, action){
    	return { ... }; //불변성을 지키면서 업데이트한 새로운 상태를 반환
    }
  • action을 형태
    • {
      	type : 'INCREMENT', 
          ... //다른 값이 필요할 경우 추가로 들어감
      }
  • import React, { useReducer } from "react";
    function reducer(state, action) {
      //action.type에 따라 다른 작업 수행
      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의 첫 번째 파라미터에는 리듀서 함수를 넣고, 두 번째 파라미터에는 해당 리듀서의 기본값을 넣어 준다.
    • Hook를 사용하면 state값과 dispatch값을 받아 오는데 state는 현재 가리키고 있는 상태, dispatch는 액션을 발생시키는 함수이다.
    • dispatch(action)과 같은 형태로, 함수 안에 파라미터로 액션 값을 넣어주면 리듀서 함수가 호출되는 구조이다.
    • 리듀서의 가장 큰 장점은 컴포넌트 업데이트 로직을 컴포넌트 바깥으로 빼낼 수가 있다는 점이다.
  • import React, { useState } from "react";
    import Counter from "./Counter";
    //import Info from "./Info";
    const App = () => {
      return <Counter />;
    };
    
    export default App;
  • 인풋 상태 관리하기
    • 전에는 인풋이 여러 개여서 여러 개의 useState를 사용하였지만 useReducer를 활용하면 기존의 클래스 컴포넌트에서 사용했던 input 태그에 name값을 할당하고 e.target.name을 참조하여, setState를 해줄 수 있다.
    • import React, { useEffect, useState, useReducer } from "react";
      function reducer(state, action) {
        return {
          ...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>
                <b>이름:</b> {name}
              </div>
              <div>
                <b>닉네임:</b>
                {nickname}
              </div>
            </div>
          </div>
        );
      };
      export default Info;
    • 이벤트 객체가 지니고 있는 e.target 값 자체를 액션 값으로 사용하여 인풋의 개수가 많아져도 코드를 깔끔하게 유지가 가능하다.
    • import React, { useState } from "react";
      import Info from "./Info";
      const App = () => {
        return <Info />;
      };
      
      export default App;

 

728x90

'리액트 > Hooks' 카테고리의 다른 글

ch06.useRef  (0) 2021.11.16
ch05.useCallback  (0) 2021.11.16
ch04.useMemo  (0) 2021.11.16
ch02.useEffect  (0) 2021.11.15
ch01.useState  (0) 2021.11.15