(React) Trendy React : useReducer

yunsungyang-omc·2021년 9월 10일
0

React

목록 보기
27/28

useReducer는 State를 다루는 관점과 방법 정도이고, useState로 작성할때에 비해 작성해야 하는 코드의 양이 많으므로 어떻게 활용하면 좋을지 감을 잡기 어렵다.

간단히 이해하고 넘어가도록 해보자


useState

import React, { useState } from 'react'
import { useRouteMatch } from 'react-router';

const useUser = () => {
  const [isAdmin, setBeAdmin] = useState(false)
  const [nickname, setnNickname ] = useState('');
  const [email, setEmail] = useState('')

  const reset = () => {
    setBeAdmin(false)
    setnNickname('')
    setEmail('')
  }
  const toggleTobeAdmin = () => setBeAdmin(!admin)
  const updateNickname = event => {
    const nickname = event.target.value
    
    setNickname(nickname)
  }
  const updateEmail = event => {
    const email = event.tartget.value
    setEmail(email)
  }
  return {
    isAdmin,
    nickname,
    email,
    reset,
    toggleTobeAdmin,
    updateNickname,
    updateEmail,
  }
}

const User = () => {
  const user = useUser()

  let label = 'user'
  if (user.isAdmin) {
    label = 'admin'
  }

  return (
    <div>
      <label>{label}</label>
      <h1>{user.name}</h1>
      <h3>{user.email</h3>
      <button onClick={user.reset}>Reset</button>
      <button onClick={user.toggleTobeAdmin}>toggle admin mode </button>
      <input type='text' onChange={user.updateNickname} />
      <input type='text' onChange={user.updateEmail} />
    </div>
  )
}

React는 State를 변경하면 바뀐부분을 새로 그리기 위해 해당하는 모든 컴포넌트를 다시 실행한다.

간단한 프로젝트 일때는 충분히 잘 동작하지만, 프로젝트의 스케일이 클수록 퍼포먼스가 중요하기 때문에 최적화에 신경을 써야 한다.

import React, { useState } from 'react'

const useUsesr = () => {
  const [user, setUser] = useState({
    isAdmin: false,
    nickname: '',
    email: ''
  })
  
  const reset = () => setUser({
    isAdmin: false,
    nickname: '',
    email: ''
  })
  const toggleTobeAdmin = () => setUser(user => ({
    ...user, isAdmin: !user.isAdmin
  }))
  const updateNickname = event => setUser(user => ({ ...user, nickname: event.target.value }))
  const updateEmail = event => setUser(user => ({ ...user, email: event.target.value }))
  
  return {
    isAdmin,
    nickname,
    email,
    reset,
    toggleToBeAdmin,
    updateNickname,
    updateEmail
  }
}

const user = () => {
  const user = useUser()
  
  let label = 'user'
  if (user.isAdmin) {
    label = 'admin'
  }
    return (
    <div>
      <label>{label}</label>
      <h1>{user.name}</h1>
      <h3>{user.email}</h3>
      <button onClick={user.reset}>RESET</button>
      <button onClick={user.toggleToBeAdmin}>toggle admin mode</button>
      <input type='text' onChange={user.updateNickname} />
      <input type='text' onChange={user.updateEmail} />
    </div>
  )
}

React Hooks를 사용한다면 isAdmin, nickname, email와 같은 여러 state를 1개의 state로 줄이는 것이 가장 먼저 시도해 볼 수 있는 최적화이다.

1개의 state를 줄인 코드보다 더 일관적인 방법으로 작성하기 위해 useReducer를 사용해보도록 하자.


useReducer

import React, { useReducer } from 'react'

const initialUserState = {
  isAdmin: false,
  nickname: '',
  email: ''
}

const userReducer = (state, action) => {
  switch (action.type) {
    case 'reset': {
      return initialUserState
    }
    case 'toggleToBeAdmin': {
      return { ...state, isAdmin: !state.isAdmin }
    }
    case 'updateNickname': {
      return { ...state, nickname: action.nickname }
    }
    case 'updateEmail': {
      return { ...state, email: action.email }
    }
    default: {
      throw new Error(`unexpected action.type: ${action.type}`)
    }
  }
}

const User = () => {
  const [user, dispatchUser] = useReducer(userReducer, initialUserState)

  let label = 'user'
  if (user.isAdmin) {
    label = 'admin'
  }

  const reset = () => dispatchUser({ type: 'reset' })
  const toggleToBeAdmin = () => dispatchUser({ type: 'toggleToBeAdmin' })
  const updateNickname = event => dispatchUser({ type: 'updateNickname', nickname: event.target.value })
  const updateEmail = event => dispatchUser({ type: 'updateEmail', email: event.target.value })

  return (
    <div>
      <label>{label}</label>
      <h1>{user.name}</h1>
      <h3>{user.email}</h3>
      <button onClick={reset}>RESET</button>
      <button onClick={toggleToBeAdmin}>toggle admin mode</button>
      <input type='text' onChange={updateNickname} />
      <input type='text' onChange={updateEmail} />
    </div>
  )
}

useReducer를 이용하면 이렇게 작성할 수 있다.

useState와 비슷하게 return 배열의 1번째에는 state가, 2번째에는 State를 변경하는 함수가 있다.

useState의 State를 변경하는 함수는 넘긴 값을 그대로 다음 State로 사용하지만, useReducer의 state를 변경하는 함수는 reducer를 거치면서 추가적으로 가공한 state를 사용할 수 있다.

useReducer는 일관적인 구조를 가지고 있기 때문에 코드의 양이 늘어날 수는 있지만 보다 더 체계적이라는 느낌을 준다.

profile
개발하는 마케터, 호두파파입니다.

0개의 댓글