본문 바로가기
React

초 간단 Redux 사용법

by 붕어사랑 티스토리 2022. 11. 8.
반응형

https://redux.js.org/tutorials/quick-start

 

Quick Start | Redux

- How to set up and use Redux Toolkit with React-Redux

redux.js.org

 

 

Redux란?

state를 관리해주는 라이브러리

 

 

왜씁니까?

state를 선언했는데 이를 어디 저 밑에 있는 자식컴포넌트한테 줘서 쓸일이 있다고 칩시다.

그럼 죄다 props 뚫어줘서 state랑 setState함수 넘겨줘야 되는데 끔찍함.

 

그래서 state를 전역으로 관리하는게 필요할 때 씀

 

 

1. 설치

npm install @reduxjs/toolkit react-redux

 

 

2. 개념

알아둬야할 개념 세가지가 있음

  • Store : 말그대로 상태를 저장하는곳
  • Provider : Store를 리액트 컴포넌트에 전달하는 놈
  • Slice : 저장될 상태, Store에 저장됨
  • Reducer : Slice의 상태값을 변경하는 함수들, setState 같은놈들이라 생각하면 된다.

 

 

 

3. 사용법

일단 본 내용은 Create-React-App 라이브러리로 프로젝트를 만들었다고 가정

 

 

 

Store생성하기

src/app/store.js에 스토어를 만듭시다. 아래와 같은 코드를 입력해줍니다.

import { configureStore } from '@reduxjs/toolkit'

export default configureStore({
  reducer: {}
})

 

 

Provider로 나의 리액트 App에 Store전달

보통 프로바이더는 리액트 컴포넌트 최상단에 넣어 놓는게 편합니다. 그래야 모든 컴포넌트들이 스토어를 사용하니깐요.

src/index.js 에 아래와 같이 프로바이더를 전달해줍니다.

import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'
import store from './app/store'
import { Provider } from 'react-redux'

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
)

 

 

Slice 만들기

slice는 전역으로 관리될 state입니다. slice를 만들 때는 다음과 같은 값들을 정의해줘야 합니다.

 

  • name : slice들을 구분짓는 이름
  • initialState : state의 초기값
  • reducers : state값을 변경해줄 함수들

src/features/counter/counterSlice.js 에 슬라이스 파일을 만들어 봅시다.

import { createSlice } from '@reduxjs/toolkit'

export const counterSlice = createSlice({
  name: 'counter',
  initialState: {
    value: 0
  },
  reducers: {
    increment: state => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.value += 1
    },
    decrement: state => {
      state.value -= 1
    },
    incrementByAmount: (state, action) => {
      state.value += action.payload
    }
  }
})

// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counterSlice.actions

export default counterSlice.reducer

 

 

 

여기서 아래와 같은 궁금증이 들 수 있음

 

어라 리듀서 함수들을 보니 state를 바꾸는 함수를 미리 정의하네요? 불편하게 왜 그럼? 걍 setState로 값 내맘대로 넣으면 안됨?

 

개발자 피셜 setState로 내가 원하는 값 손쉽게 변경하면 편하긴 한데, 버그가 생길경우 디버깅이 힘들다 함.

그래서 값을 update하는 함수를 미리 정의하면 좀 불편하지만 버그 추적이 쉬워서 저리 만든듯

 

 

 

Slice를 Store에 붙여주기

store에 slice를 붙여주려면 slice의 reducer 파라미터를 사용하면 된다. 위 코드에서 counterSlice.reducer를 export한걸 import 하여 스토어에 붙여주자

 

app/store.js

import { configureStore } from '@reduxjs/toolkit'
import counterReducer from '../features/counter/counterSlice'

export default configureStore({
  reducer: {
    counter: counterReducer
  }
})

 

 

 

 

본격적으로 state 사용하기

다음 두가지만 기억하면 된다

 

  • useSelector : store에 저장된 state를 가져오는 hook
  • useDispatch : state를 변경하기 위해 reducer를 호출하는 함수

 

useSelector는 다음과 같은 형태로 사용한다.

 

useSelector(state.스토어에 저장된 state.value);

 

useDispatch는 다음과 같은 형태로 사용한다

 

const dispatch = useDispatch();

dispatch(state값을 변경할 reducer함수());

 

import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { decrement, increment } from './counterSlice'
import styles from './Counter.module.css'

export function Counter() {
  const count = useSelector(state => state.counter.value)
  const dispatch = useDispatch()

  return (
    <div>
      <div>
        <button
          aria-label="Increment value"
          onClick={() => dispatch(increment())}
        >
          Increment
        </button>
        <span>{count}</span>
        <button
          aria-label="Decrement value"
          onClick={() => dispatch(decrement())}
        >
          Decrement
        </button>
      </div>
    </div>
  )
}

 

 

 

 

 

 

 

잠깐만요. 저 위에 increamentByAmount는 setState같이 쓰는 함수인거 같은데 어케 쓰나요?

 

요거요?

incrementByAmount: (state, action) => {
  state.value += action.payload
}

 

이렇게 쓰시면 됩니다.

dispatch(incrementByAmount(10));

그럼 10이 action.payload로 값이 넘어옵니다.

반응형

댓글