useReducer

김석·2023년 9월 19일
0

React

목록 보기
7/14

1. useReducer

  • useState는 컴포넌트 안에서 상태를 관리함
  • useReducer는 컴포넌트 상태 업데이트 로직을 컴포넌트와 분리시킬 수 있음
  • 즉, 상태 업데이트 로직을 컴포넌트 바깥에 작성할 수 있음
function reducer(state, action) {
  // 새로운 상태를 만드는 로직
  // const nextState = ...
  return nextState;
}
  • reducer는 현재 상태와 액션 객체를 받아서, 새로운 상태를 반환하는 함수.
  • reducer에서 반환하는 상태가 곧 컴포넌트가 지닐 새로운 상태
  • action: 업데이트를 위한 정보, 주로 type 값을 지닌 객체 형태로 사용
// 카운터에 1을 더하는 액션
{
  type: 'INCREMENT'
}
// 카운터에 1을 빼는 액션
{
  type: 'DECREMENT'
}
// input 값을 바꾸는 액션
{
  type: 'CHANGE_INPUT',
  key: 'email',
  value: 'tester@react.com'
}
// 새 할 일을 등록하는 액션
{
  type: 'ADD_TODO',
  todo: {
    id: 1,
    text: 'useReducer 배우기',
    done: false,
  }
}
  • action 객체는 자유 형태지만, type 값을 대문자와 _로 구성하는 관습이 있음.

사용법

const [state, dispatch] = useReducer(reducer, initialState);
  • state: 앞으로 컴포넌트에서 사용할 상태
  • dispatch: 액션을 발생시키는 함수. dispatch({ type: 'INCREMENT' })로 사용
  • useReducer의 첫 번째 파라미터: reducer 함수
  • useReducer의 두 번째 파라미터: 초기 상태
import React, { useReducer } from 'react';

const initialState = 0;

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

function Counter() {
  const [number, dispatch] = useReducer(reducer, initialState);

  const onIncrease = () => {
    dispatch({ type: 'INCREMENT' });
  };

  const onDecrease = () => {
    dispatch({ type: 'DECREMENT' });
  };

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={onIncrease}>+1</button>
      <button onClick={onDecrease}>-1</button>
    </div>
  );
}

export default Counter;
  • initialState는 바뀌지 않음. 그냥 초기 값을 세팅하는 용도로 쓰이고 끝.
  • 실제로 바뀌는 것은 function 내부의 number라는 state

2. 실제 코드

import React, { useRef, useReducer, useMemo, useCallback } from 'react';
import UserList from './UserList';
import CreateUser from './CreateUser';

function countActiveUsers(users) {
  console.log('활성 사용자 수를 세는중...');
  return users.filter(user => user.active).length;
}

const initialState = {
  inputs: {
    username: '',
    email: ''
  },
  users: [
    {
      id: 1,
      username: 'velopert',
      email: 'public.velopert@gmail.com',
      active: true
    },
    {
      id: 2,
      username: 'tester',
      email: 'tester@example.com',
      active: false
    },
    {
      id: 3,
      username: 'liz',
      email: 'liz@example.com',
      active: false
    }
  ]
};

function reducer(state, action) {
  switch (action.type) {
    case 'CHANGE_INPUT':
      return {
        ...state,
        inputs: {
          ...state.inputs,
          [action.name]: action.value
        }
      };
    default:
      return state;
  }
}

function App() {
  const [state, dispatch] = useReducer(reducer, initialState);
  const { users } = state;
  const { username, email } = state.inputs;

  const onChange = useCallback(e => {
    const { name, value } = e.target;
    dispatch({
      type: 'CHANGE_INPUT',
      name,
      value
    });
  }, []);

  return (
    <>
      <CreateUser username={username} email={email} onChange={onChange} />
      <UserList users={users} />
      <div>활성사용자 수 : 0</div>
    </>
  );
}

export default App;
  • App 컴포넌트 밖에 reducer, initialState 정의
  • 앱 내부에서 state 내부의 상태들을 참조
  • 상태 변경 로직을 dispatch를 통해 reducer에 전송
  • reducer에서 상태 변경 로직 정의
  • state는 현재 상태를 뜻함
  • action은 distpatch로 전달된 객체를 의미
  • action으로 전달된 정보를 사용해서 reducer에서 return으로 state를 업데이트함
profile
handsome

0개의 댓글

Powered by GraphCDN, the GraphQL CDN