3 분 소요

Redux는 props drilling을 피하고 전역 상태관리를 위한 라이브러리이다.

사용 방법에 대해 여러 블로그와 공식문서를 참고하여 연습해봤다.

사용 방법

1. Action 을 만든다.

useState를 쓰지 않는 Redux에서는 프로퍼티로 type이 들어가는 객체를 선언해야 한다.

const junyub = { type: "JUNYUB" };

action을 만드는데에는 두가지방법이 있다.

위처럼 object 자료형을 선언하는 방법과, 액션생성 함수를 만드는 방법이 있다.

function junyub (num) {
	return { type: "JUNYUB", payload: num } 
}

액션 생성함수를 만들어주게 되면, 항상 동일한 객체가 return 된다는 점이 다르다.

이 액션을 선언하면, 나중에 dispatch를 통해 스토어에 전달하게 되는데, 그때 dispatch함수 아규먼트 자리에 함수를 쓸거냐, object자료형을 쓸거냐의 차이이다.

2. reducer를 작성한다.

하나의 state에 변경할 함수 로직들을 작성하는 reducer를 만들어야 한다.

function junyubReducer(state = {count: 0}, action) {
	switch(action.type){
		case "JUNYUB":
			return { ...state, count: state.count + action.payload }
		default:
			return state;
	}
}

reducer함수에는 파라미터가, 적용할 state가 첫번째, action 객체가 두번째이다.

우리가 선언했던, 액션이라는 객체가 두번째 파라미터로 들어오게되고, 선언했던 type파라미터자리가 switch문에 action.type으로 들어간게 보인다. state가 어떻게 변경될지에 따라 액션 생성을 추가하여 switch문의 case에 추가한다.

보통 이 action 과 reducer는 redux폴더에 module 파일에 작성한다고 한다.

리액트 프로젝트에서 리덕스 라이브러리를 사용한다면, 경로를 위와 같이 지정한다

Untitled

지금까지 만들었던 action과 reducer들은 module.js 파일에 들어가고,

그 리듀서들을 스토어에 등록해야 된다.

3. store를 만들고, reducer를 등록

import { combineReducers, createStore } from 'redux';
import { countReducer, reducer } from './module';

const rootReducer = combineReducers({
  reducer: reducer,
  countReducer: countReducer,
})

export const store = createStore(rootReducer);

프로젝트에서 전체적으로 store는 하나이다.

프로젝트에서 하나의 상태만 관리하는게 아니기 때문에, combineReducers로 정의했던 상태변경 리듀서들을 rootReducer라는데에 모아버린다.

위에서의 코드는 두개의 리듀서가 rootReducer에 combineReducers()함수를 통해 등록되는 것이다.

다시말해, 여러 리듀서가 존재하지만, 그걸 하나로 합쳐주는게 combineReducer() 함수고, 그걸 rootReducer라는 변수에 담았다.

그리고 store에는 rootReducer만 올라가면 모든 리듀서가 store에 올라가게 된다.

이렇게 하는 이유는, store를 여러개 생성할 수 없기 때문이다.

4. 상태관리를 적용할 컴포넌트에 Provider 등록

보통 전역상태관리에 의의가 있으니 index.js 나 app.js에 작성하긴 한다.

// App.js
import React, { useState } from 'react';
import { Provider } from 'react-redux';
import { Main } from './components/Main';
import { store } from './redux/store';

export default function App() {
  return (
    <div id="container">
      <h1>Root</h1>
      <div id="grid">
        <Provider store={store}>
          <Left1 />
          <Right1 />
          <Main/>
        </Provider>
      </div>
    </div>
  );
}

하위 컴포넌트들인 Left1, Right1, Main 컴포넌트에서 store에 담긴 상태들을 갖고가서 쓸 수 있다.

Left1에 자식 컴포넌트, Right1의 자식컴포넌트 등등 app.js 파일에서 보이지 않는 자식컴포넌트들에게도 상태관리가 가능하다.

5. useSelector랑 useDispatch써서 상태관리하기

Main 컴포넌트에서 상태관리를 한다고 가정하자.

useSelector는, 말 그대로 store에 등록되어 있는 state를 선택하는거다.

사용 방법은 다음과 같다

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { counterAdd, counterMinus } from '../redux/module';

export const Main = () => {
  const number = useSelector((state) => state.countReducer.count);
  const dispatch = useDispatch();

  return (
    <div>
      <h1>{number}</h1>
      <button onClick={()=> {dispatch(counterAdd(5))}}>+</button>
      <button onClick={()=> {dispatch(counterMinus(5))}}>-</button>
    </div>
  )
}

먼저, react-redux에서 useDispatch와 useSelector를 import 해와야 하고,

Main 컴포넌트에서

const number = useSelector((state) ⇒ state.countReducer.count); 한거가 보인다.

우리가, 리듀서를 만들때, 그 리듀서 이름이 countReducer였을거고, 그 안에 들어간 state 이름이 count 였다.

export function countReducer(state={count : 0}, action){
  switch(action.type){
    case "COUNTER":
      return { ...state, count: state.count + action.payload }
    case "MINUS":
      return { ...state, count: state.count - action.payload }
    default:
      return state;
  }
}

이렇게 쓰이니깐 리듀서 작명과, state 작명도 잘 해야된다.

어쨌든, 스토어에 있는 리듀서를 보고, state를 선택해서 number라는 변수에 담았다.

그럼 이제 리듀서에 등록되어 있던 상태변경을 어떻게 하는지 보겠다.

버튼이 두개있고 onclick했을때 콜백함수로 dispatch가 실행된다.

그리고 dispatch() 아규먼트 안에 함수 실행이 또 있다. counterAdd(5);

이건, 우리가 액션을 만들때 액션생성함수로 정의해서 이렇게 쓸 수 있는거다.

function counterAdd(num){
	return { type: "COUNTER" , payload: num }
}

counterAdd(5)라는건 결국 { type : “COUNTER” , payload: 5 } 를 dispatch로 넘겨주는 것과 똑같다.

여튼 저렇게 객체가 넘어가면, store에 있는 reducer에 전달이 되고 switch문에 있는 case들 중 return할 작업을 마친다음 상태를 변경해준다.

리덕스를 쓸 때 기억해야 할건 다섯가지

  1. 액션을 만든다. (객체로든 함수로든)
  2. 리듀서를 만든다. (하나의 state를 관리할 리듀서이다)
  3. 스토어에 리듀서를 등록한다 (여러개의 리듀서라면 combineReducers로 합치는 작업 필요)
  4. 전역상태관리니깐 Provider 범위설정해준다.
  5. useSelector, useDispatch써서 상태 선택, 변경 진행

이런 순서로 작성해주면 되고, 파일구조도 조심해서 사용하면 되겠다.

댓글남기기