본문 바로가기
React

[리액트] useReducer 사용법

by 메이플 🍁 2022. 8. 21.

useReducer란?

  • useReducer는 상태 관리를 담당하는 훅을 말한다
  • useState는 단순히 상태 관리를 해주는 훅이라면 useReducer는 해당 상태를 업데이트할때 유용한 Hook이다
  • useReducer는 useState를 통한 상태 관리 + 상태 추가, 제거, 수정 등의 핸들러를 하나의 함수로 사용할 수 있도록 해준다

 

기본문법

const [state, dispatch] = useReducer(리듀서 이름, 초기 데이터)

state 데이터

  • state는 상태 즉 데이터다
  • useReducer 함수의 두번째 인자로 들어가는 초기 데이터를 1로 설정하면 state의 값도 1이 된다
  • 즉 useReducer 함수에 등록한 초기데이터는 state로 접근할 수 있게 된다

dispatch 함수

  • state를 처리하기 위한 함수다
  • 데이터의 값을 추가, 제거, 수정을 위한 함수다
  • dispatch 함수 안에 등록한 타입(추가, 제거, 수정 등)을 명시해주면 해당 로직이 실행된다
  • 예를 들어 dispatch({type: 'ADD'}) 함수를 호출하면 데이터 추가 작업이 실행된다
  • dispatch 함수의 인자로 특정한 작업 타입을 명시해주면 타입에 따라 등록한 함수를 실행해주는 역할을 한다

reducer 함수

  • dispatch 함수에서 특정 type을 인자로 받을때 실행할 로직을 정해준다
  • 아래의 코드처럼 reducer 함수를 생성하면 dispatch 함수의 인자로 {type: 'ADD'}가 들어왔을때 case 'ADD'인 로직이 실행된다
export function userReducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return [...state, action.data]
    default:
      throw new Error(`Unhandled action type: ${action.type}`)
  }
}

action

  • userReducer 함수의 두번째 인자로 들어 있는 값
  • dispatch 함수 실행시 인자로 넣어준 값을 받아온다
  • dispatch({type: 'ADD'})가 호출된 경우에는 action은 {type: 'ADD'} 객체가 되며 switch 검사문에서 받는 action.type은 'Add'가 된다

 

예제

userData.js

export const userData = [
  {
    id: 1,
    name: 'Leanne Graham',
    email: 'Sincere@april.biz',
  },
  {
    id: 2,
    name: 'Ervin Howell',
    email: 'Shanna@melissa.tv',
  },
  {
    id: 3,
    name: 'Clementine Bauch',
    email: 'Nathan@yesenia.net',
  },
  {
    id: 4,
    name: 'Patricia Lebsack',
    email: 'Julianne.OConner@kory.org',
  },
  {
    id: 5,
    name: 'Chelsey Dietrich',
    email: 'Lucio_Hettinger@annie.ca',
  },
  {
    id: 6,
    name: 'Mrs. Dennis Schulist',
    email: 'Karley_Dach@jasper.info',
  },
  {
    id: 7,
    name: 'Kurtis Weissnat',
    email: 'Telly.Hoeger@billy.biz',
  },
  {
    id: 8,
    name: 'Nicholas Runolfsdottir V',
    email: 'Sherwood@rosamond.me',
  },
  {
    id: 9,
    name: 'Glenna Reichert',
    email: 'Chaim_McDermott@dana.io',
  },
  {
    id: 10,
    name: 'Clementina DuBuque',
    email: 'Rey.Padberg@karina.biz',
  },
]

 

userList.jsx

import React, { useReducer, useRef, useState } from 'react'
import { userData } from '../constant/userData'
import { userReducer } from '../reducers/userReducer'

const UserList = () => {
  const [userInput, setUserInput] = useState({
    id: '',
    name: '',
    email: '',
  })

  const userInputHandler = (e) => {
    const { name, value } = e.target
    setUserInput({
      ...userInput,
      [name]: value,
    })
  }

  // const [state, dispatch] = useReducer(리듀서 이름, 초기 데이터)
  const [state, dispatch] = useReducer(userReducer, userData)

  const userId = useRef(11)

  const addUser = (userInput) => {
    dispatch({
      type: 'ADD',
      data: { ...userInput, id: userId.current },
    })
    userId.current += 1
  }

  const removeUser = (userId) => {
    dispatch({
      type: 'REMOVE',
      data: { id: userId },
    })
  }

  return (
    <>
      <div>
        {state.map((user) => (
          <div key={user.id}>
            <p>{user.name}</p>
            <button onClick={() => removeUser(user.id)}>제거하기</button>
          </div>
        ))}
      </div>
      <input
        type="text"
        name="name"
        placeholder="name"
        onChange={userInputHandler}
      />
      <input
        type="email"
        name="email"
        placeholder="email"
        onChange={userInputHandler}
      />
      <button onClick={() => addUser(userInput)}>이름 추가</button>
    </>
  )
}

export default UserList

 

userReducer.js

export function userReducer(state, action) {
  switch (action.type) {
    case 'ADD':
      return [...state, action.data]
    case 'REMOVE':
      return state.filter((el) => el.id !== action.data.id)
    default:
      throw new Error(`Unhandled action type: ${action.type}`)
  }
}

 

App.jsx

import React from 'react'
import UserList from './components/UserList'

const App = () => {
  return (
    <div>
      <UserList />
    </div>
  )
}

export default App

댓글