JS' 공부흔적

[React Redux] React에서 Redux를 사용해보자(1) 본문

Redux

[React Redux] React에서 Redux를 사용해보자(1)

이준수 2022. 1. 22. 03:30

이 글은 Redux의 기본 개념에 대해 알고 있다고 가정하고 진행한다. 개념을 잘 모른다면 아래 포스팅을 참고하면 좋을 듯!

 

[Redux] Vanilla Redux의 기본 개념

Redux는 Javascript의 상태 관리 라이브러리이다. 보통 React와 함께 많이 사용되지만, Augular, jQuery, vanilla JavaScript 등 여러 framework에서 사용이 가능하다. Redux에 기본적인 개념 및 용어를 알아보자..

2junsu.tistory.com


할 일을 추가하고 삭제할 수 있는 간단한 Todo List를 구현하면서 React에서 Redux를 사용하는 법을 알아보자. 이 글에서는 '추가' 기능을 구현한다. 또한 Redux에 익숙해지기 위한 글이므로 Local Storage는 사용하지 않는다. 우선 Redux 사용에 필요한 action, reducer, store는 아래 코드에 바로 작성했다.

import { createStore } from 'redux'

const ADD = 'ADD'
const DELETE = 'DELETE'

//할 일 추가는 text가 필요하다.
const addTodo = (text) => {
  return { type: ADD, text }
}

//할 일 삭제는 해당 할 일의 id를 이용하여 찾아낸 후 삭제한다.
const deleteTodo = (id) => {
  return { type: DELETE, id }
}

const reducer = (state = [], action) => {
  switch (action.type) {
    //각 할 일 별로 id를 부여함
    case ADD: //state를 mutate 불가
      return [...state, { text: action.text, id: Date.now() }]

    //filter함수를 사용하여 받은 id의 할 일을 제외하고 나머지를 리턴 -> 받은 id의 할 일만 빠진다.
    case DELETE:
      return state.filter((e) => e.id !== action.id)
    default:
      return state
  }
}

const store = createStore(reducer)

export const ActionCreators = { addTodo, deleteTodo } //Action Creator

export default store

위의 코드에서 잘 봐야할 것은 reducer의 ADD 부분이다. Todo List에 할 일을 추가하는 부분인데, 이를 배열에 저장한다. 일반적으로는 배열의 push() 함수를 사용하여 값을 추가하지만, reducer는 다르다. Redux의 state는 불변성을 유지해야 한다. 즉, state를 mutate할 수 없다는 말인데 이는 state의 값을 직접 다이렉트로 변경할 수 없다는 말이다. 따라서 배열의 push() 함수를 사용하여 배열의 값을 직접적으로 변경할 수 없고, 간접적으로 새로운 배열을 생성하여 이 배열을 반환해야 한다. 이 부분은 중요하니까 꼭 알아뒀으면 한다!

 

Vanilla Redux에서 다룬 개념 중 dispatch, getState, subscribe는 쓰이지 않았는데 React Redux에서는 사용하는 법이 약간 다르다. mapDispatchToProps, mapStateToProps, connect가 그 방법인데 이는 주로 예전에 쓰이던 방법이고, 요즘에는 Hook을 사용하여 더 편리하게 Redux에 접근할 수 있는 방법이 등장했기 때문에 이 방법으로 설명하겠다. 그러나 클래스형 컴포넌트를 사용한다면 Hook을 사용하지 못 하므로 아래의 Docs를 참고하길 바란다.

 

React Redux | React Redux

Official React bindings for Redux

react-redux.js.org


npm install react-redux

yarn add react-redux

useDispatch

dispatch를 React Redux에서는 useDispatch로 사용한다. 사용법은 거의 비슷하다. 우리가 Todo List에서 dispatch가 필요한 곳은 할 일을 추가하거나 삭제할 때이다. 할 일을 추가할 때부터 보면 입력했을 때 dispatch가 발생해야 한다. 따라서 form 태그를 사용하여 간단한 입력 폼을 만들고 onSubmit을 사용하여 dispatch를 구현할 수 있다.

import React, { useState } from 'react'
import Todo from './Todo'
import { useDispatch } from 'react-redux'
import { ActionCreators } from './redux/store'

const App = () => {
  const dispatch = useDispatch() //useDispatch Hook을 사용하는 방법
  const [text, setText] = useState('')

  const onChange = (e) => {
    setText(e.target.value)
  }

  const onSubmit = (e) => {
    e.preventDefault() //제출을 해도 페이지가 넘어가지 않도록 유지
    console.log(text)
    dispatch(ActionCreators.addTodo(text)) //addTodo함수로 action 생성 후 dispatch
    setText('')
  }
  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      <h1>react redux 연습</h1>
      <form onSubmit={onSubmit}>
        <input type="text" value={text} onChange={onChange} />
        <button>ADD</button>
      </form>
      ...
    </div>
  )
}

export default App

useSelector

getState()는 useSelector라는 Hook을 사용하여 구현한다. store에서 원하는 값을 골라온다는 뜻이다. 이것의 사용 방법도 복잡하지 않다. 단지 아래의 코드만 추가해주면 된다.

import { useSelector } from 'react-redux'
const todoList = useSelector((state) => state)
console.log(todoList) //값을 확인하기 위함

input 창에 '잠자기'를 입력한 후 로그를 찍어보면 아래와 같이 뜬다.

따라서 이 데이터를 화면에 뿌려주기만 하면 '추가' 기능은 완성이다!

//App.js
import React, { useState } from 'react'
import Todo from './Todo'
import { useDispatch, useSelector } from 'react-redux'
import { ActionCreators } from './redux/store'

const App = () => {
  const dispatch = useDispatch()
  const todoList = useSelector((state) => state)
  console.log(todoList)
  const [text, setText] = useState('')

  const onChange = (e) => {
    setText(e.target.value)
  }

  const onSubmit = (e) => {
    e.preventDefault()
    console.log(text)
    dispatch(ActionCreators.addTodo(text))
    setText('')
  }
  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
      }}
    >
      <h1>react redux 연습</h1>
      <form onSubmit={onSubmit}>
        <input type="text" value={text} onChange={onChange} />
        <button>ADD</button>
      </form>
      <div
        style={{
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          width: 300,
        }}
      >
        <h3>할 일</h3>
        <ul>
          {todoList.map((e) => (
            <Todo key={e.id} {...e} />
          ))}
        </ul>
      </div>
    </div>
  )
}

export default App
//Todo.js
import React from 'react'

const Todo = (text) => {
  return (
    <li>
      {text} <button>DEL</button>
    </li>
  )
}

export Todo

 

728x90
반응형