React

[리액트] Redux

드비디 2024. 10. 22. 14:39

Redux란 무엇인가?

Redux(리덕스)란 JavaScript(자바스트립트) 상태관리 라이브러리이다.

Redux(리덕스)의 본질은 Node.js 모듈이다.

 

Redux를 사용하는 이유

 먼저 상태란?

  • React에서 State는 component 안에서 관리되는 것이다.
  • 자식 컴포넌트들 간의 다이렉트 데이터 전달은 불가능 하다.
  • 자식 컴포넌트들 간의 데이터를 주고 받을 때는 상태를 관리하는 부모 컴포넌트를 통해서 주고 받는다.
  • 그런데 자식이 많아진다면 상태 관리가 매우 복잡해진다.
  • 상태를 관리하는 상위 컴포넌트에서 계속 내려 받아야한다. => Props drilling 이슈

 

Redux의 사용의 좋은 예는 props즉 상태를 전이 할 때 한 단계식 내리는것이 아닌 store를 통해 밖에서 상태를 전달해줄 수가 있다.

 

Store (스토어)

Store(스토어)는 상태가 관리되는 오직 하나의 공간이다.

  • 컴포넌트와는 별개로 스토어라는 공간이 있어서 그 스토어 안에 앱에서 필요한 상태를 담는다.
  • 컴포넌트에서 상태 정보가 필요할 때 스토어에 접근한다.

Action (액션)

  • Action(액션)은 앱에서 스토어에 운반할 데이터를 말한다. (주문서)
  • Action(액션)은 자바스크립트 객체 형식으로 되어있다.

 Reducer (리듀서)

  • Action(액션)을 Store(스토어)에 바로 전달하는 것이 아니다.
  • Action(액션)을 Reducer(리듀서)에 전달해야한다.
  • Reducer(리듀서)가 주문을 보고 Store(스토어)의 상태를 업데이트하는 것이다.
  • Action(액션)을 Reducer(리듀서)에 전달하기 위해서는 dispatch() 메소드를 사용해야한다..

Redux 간단하게 시작해보기

# NPM
npm install redux
npm install react-redux

# Yarn
yarn add redux react-redux

먼저 리덕스를 설치한다.

1. RootReducer 정의

  • 여러 reducer을 사용하는 경우 reducer을 하나로 묶어주는 메소드
// reducers/index.js

import { combineReducers } from "redux";
import counter from "./counter";

const rootReducer = combineReducers({
  counter
});

export default rootReducer;

2. 세부 reducer 정의

// reducers/counter.js

export const INCRESE = "COUNT/INCRESE";

export const increseCount = count => ({ type: INCRESE, count });

const initalState = {
  count: 0
};

const counter = (state = initalState, action) => {
  switch (action.type) {
    case INCRESE:
      return {
        ...state,
        count: action.count
      };

    default:
      return state;
  }
};

3. store 만들기

import { compose, createStore, applyMiddleware } from "redux";
import rootReducer from '../reducers/index';
import thunk from "redux-thunk";

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({})
  : compose;
const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk)));

export default store;

4. app에 store 넣고, 만든 reducer 반영

<Provider> 안써서 엄청나게 눈물을 흘리면서 왜 안될까 찾았던…

// index.js
import React from "react";
import ReactDOM from "react-dom";
import { createStore, applyMiddleware, compose } from "redux";
import { Provider } from "react-redux";
import logger from "redux-logger";
import { composeWithDevTools } from "redux-devtools-extension";

import App from "./App";
import rootReducer from "./reducers";

// 배포 레벨에서는 리덕스 발동시 찍히는 logger를 사용하지 않습니다.
const enhancer =
  process.env.NODE_ENV === "production"
    ? compose(applyMiddleware())
    : composeWithDevTools(applyMiddleware(logger));

// 위에서 만든 reducer를 스토어 만들때 넣어줍니다
const store = createStore(rootReducer, enhancer);

ReactDOM.render(
  // 만든 store를 앱 상위에 넣어줍니다.
  <Provider store={store}>
    <App />
  </Provider>
  document.getElementById('root'),
);

5. 컴포넌트에서 redux 사용하기

import { useSelector, useDispatch } from "react-redux";
import { increseCount } from "reducers/count";

// dispatch를 사용하기 위한 준비
const dispatch = useDispatch();

// store에 접근하여 state 가져오기
const { count } = useSelector(state => state.counter);

const increse = () => {
  // store에 있는 state 바꾸는 함수 실행
  dispatch(increseCount());
};

const Counter = () => {
  return (
    <div>
      {count}
      <button onClick={increse}>증가</button>
    </div>
  );
};

export default Counter;

 

 

Reference

https://medium.com/@heoh06/%EB%A6%AC%EC%95%A1%ED%8A%B8-redux%EC%99%80-%EC%82%AC%EC%9A%A9%EB%B2%95-731853fc3cd4