[React] Redux랑 친해지기

서영·2022년 5월 15일
2

React

목록 보기
3/5

Redux

Redux란?

💡 자바스크립트 상태관리 라이브러리

Redux의 필요성

Component 간의 정보 공유

  • 자식 컴포넌트 간 데이터를 주고 받을 때는 상태를 관리하는 부모 컴포넌트를 통해서 주고 받아야 한다.
  • 그런데 자식이 많아지면 상태 관리가 매우매우 복잡해진다.
  • 상태를 관리하는 상위 컴포넌트에서 props를 계속 내려 받아야 한다. ⇒ Props Drilling 이슈

상태 관리의 복잡성을 해결해주는 Redux !!

✅ 전역 상태 저장소 제공을 통한 Props drilling 이슈 해결

  • 예를 들어 <A> 라는 컴포넌트에 state가 있는데 <D>라는 컴포넌트가 해당 state를 사용해야 한다면, 그 중간에 존재하는 <B>, <C> 컴포넌트는 굳이 해당 state가 필요하지 않아도 props를 만들어 자식 컴포넌트에 넘겨줘야 했다.
  • 이러한 props drilling(프로퍼티 내려꽂기) 문제를 해결하기 위해 어디서든 접근 가능한 전역 상태 저장소 Redux가 대두되었다!!

Redux의 기본 개념 : 세 가지 원칙

1. Single source of truth

  • 동일한 데이터는 항상 같은 곳에서 가지고 온다.
  • store 라는 하나뿐인 데이터 공간이 존재한다는 의미

2. State is read-only

  • React에서는 setState 또는 useState를 통해서만 상태 변경이 가능하다.
  • Redux에서도 Action(액션)이라는 객체를 통해서만 상태를 변경할 수 있다.

3. Changes are made with pure functions

  • 변경은 순수 함수로만 가능하다.
  • 리듀서와 연관되는 개념
  • Store(스토어) - Action(액션) - Reducer(리듀서)

Store, Action, Reducer의 의미와 특징

Store(스토어)

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

  • 컴포넌트와는 별개로 Store라는 공간이 존재한다.
  • 스토어 안에 필요한 state들을 담을 수 있다.
  • 컴포넌트에서 state가 필요할 때 props로 넘기지 말고 스토어에 접근해서 state를 쓸 수 있다.

Action(액션)

💡 Action(액션)은 스토어에 운반할 데이터를 말한다.

  • 스토어에 요구할 주문서라고 볼 수 있다!
  • 액션은 JS 객체 형식으로 되어있다.

Reducer(리듀서)

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

Redux의 상태 관리 도식화

Action(액션) 객체가 dispatch() 메소드에 전달된다.

dispatch(액션)를 통해 Reducer를 호출한다.

Reducer는 새로운 Store 를 생성한다.

  • 위와 같은 공식을 따르는 이유는 데이터가 한 방향으로만 흘러야하기 때문이다.

Redux에서 위 개념을 구현하는 방법 2가지

1. mapStateToProps()

2. Redux hooks

  • useSelector
  • useDispatch

Redux의 장점

  • 순수 함수(pure function)를 사용하기 때문에 상태를 예측 가능하게 만든다.
  • 복잡한 상태 관리를 할 때보다 유지보수가 편하다.
  • action과 state log를 기록하면 디버깅에 유리하다. → redux dev tool(크롬 확장 애플리케이션 이용하면 디버깅하기 쉽다)
  • 순수 함수를 사용하므로 테스트가 용이하다.

예제

  1. redux 깔기
yarn add redux react-redux
or
npm i redux react-redux
  • redux랑 react-redux를 설치해준다.
  1. redux 폴더 만들기

  • action, rootReducer, store javascript 파일을 만든다.
  1. store.js
import { createStore } from "redux";
import rootReducer from "./rootReducer";

const store = createStore(rootReducer);

export default store;
  • createStore는 첫 번째 인자로 reducer를 받는다.
  1. rootReducer.js
const initialState = {
    isLogin: false,
};

const rootReducer = (state = initialState, action) => {
    switch (action.type) {
        case "LOGIN":
            return { ...state, isLogin: action.payload };
        case "LOGOUT":
            return { ...state, isLogin: action.payload };
        default:
            return state;
    }
};

export default rootReducer;
  • 로그인 상태를 전역 변수로 다루고자 한다.

  • rootReducer에는 action과 state가 들어간다.

  • state에는 초기값을 지정해줄 수 있다. 여기서는 isLogin : false

  • action에서 “LOGIN”이라는 type 변수를 받아오면 기존 state와 isLogin의 바뀔 상태를 반환해준다.

  1. action.js
export const setLogin = () => ({
    type: "LOGIN",
    payload: true,
})

export const setLogout = () => ({
    type: "LOGOUT",
    payload: false,
})
  • setLogin 은 type은 “LOGIN”이라는 문자열이고 payload는 true값을 전달해주는 액션이다.
  • setLogin을 호출하면 변수를 true값으로 바꿔줄 수 있다.
  1. LoginPage.jsx
import { connect } from "react-redux";
import { setLogin } from "../redux/action";
  • 로그인 페이지에서 로그인 버튼을 클릭했을 때 전역state isLogin 을 true값으로 변경시켜주려고 한다.
  • 위 두 가지를 import해준다.
export default connect(null, mapDispatchToProps)(LoginPage);
  • connect를 통해 redux와 page를 연결해줄 수 있다.
  • 이 때 connect의 첫 번째 인자는 mapStateToProps 이고 두 번째 인자는 mapDispatchToProps 이다. 여기서는 state를 변경하고 있고 state를 직접 사용하는 부분이 없기 때문에 null을 할당했다.

🔻 action을 실행시키는 방법 ⇒ dispatch

const mapDispatchToProps = (dispatch) => {
  return {
    setUserLogin: () => dispatch(setLogin()),
  };
};
  • action을 dispatch하는 방법은 위와 같다.
  • setUserLogin 을 hook처럼 쓸 수 있다.
  • action.js에서 정의했던 setLogin() 을 dispatch해주는 코드이다.
  • 실행하면 store.js에 보관되어 있는 isLogin이라는 state가 true가 된다.
profile
꾸준히 공부하기

0개의 댓글