redux toolkit을 이용해 전역 상태 관리 코드를 작성하는 법을 알아봅니다. redux toolkit을 사용하면 기존 redux를 좀더 간편하게 이용할 수 있습니다.

 

redux toolkit으로 전역 상태 관리하기

 

 목차

 

1. redux toolkit이란?

2. toolkit을 사용하면 뭐가 달라지나요?

3. 구현 코드

4. 구현된 코드로 보기

함께 보면 좋은 글

 

1. redux toolkit이란?

  • redux를 더 쉽게 사용하고 관리할 수 있게 도와주는 공식 라이브러리
  • 즉, redux를 좀 더 쉽게 사용하기 위한 라이브러리

2. toolkit을 사용하면 뭐가 달라지나요?

  • 코드 간소화
    • 기존 redux는 boilertemplate(기본 코드)가 너무 길다는 단점이 있었음
    • toolkit을 통해 코드를 간략화 할 수 있음

 

  • 불변성 관리
    • 기존 redux에서는 상태 관리 로직에서 불변성 관리가 되지 않아, 기존 값을 따로 복사해야 했음
    • ex) { ...state, name: 홍길동 }
    • toolkit을 사용할 시 불변성 유지가 되기 때문에, 변경하고 싶은 값만 변경하면 됨
    • ex) state.name = "홍길동"

 

  • 개발자 도구 적용 간편
    • toolkit은 redux-devtools를 따로 설치하지 않고, 설정만 해도 적용

3. 구현 코드

  • slice 생성
    • slice는 reducer와 action을 동시에 관리함
    • 초기 상태 값 설정
    • slice 내부에 action 생성 (state의 변경 시키고 싶은 값만 수정)
    • slice를 통해 생성된 action 내보내기

 

// store/slice/infoSlice.js

import { createSlice } from "@reduxjs/toolkit";

// 초기 상태 값 설정
const initialState = { name: "홍길동", age: 20 };

// slice를 통해 action 생성
const infoSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    // 액션 생성
    // state의 변경 시키고 싶은 값만 수정
    changeName: (state, action) => {
      state.name = action.payload;
    },

    changeAge: (state, action) => {
      state.age = action.payload;
    },
  },
});

// reducer에 생성한 action export
export const { changeName, changeAge } = infoSlice.actions;
export default infoSlice.reducer;

 

  • store 생성
    • configure 함수 사용
    • reducer 등록
    • 개발자 도구 사용 설정

 

// store/store.js

import { configureStore } from "@reduxjs/toolkit";
import infoReducer from "./slice/infoSlice";

// configureStore 함수 사용
// devTools 따로 설치하지 않고 설정만 해도 사용 가능
const store = configureStore({
  // 생성한 reducer 등록
  reducer: {
    info: infoReducer,
  },
  // 개발자 도구 사용 설정 ON
  devTools: true,
});

export default store;

 

  • 가장 상위 컴포넌트에 store 등록

 

// main.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store/store";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    {/* 작성한 store 적용 */}
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

 

  • redux 사용하기
    • state 불러오기
    • dispatch 사용하기
    • dispatch를 통해 action을 store로 전달

 

// App.jsx

import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { changeAge, changeName } from "./store/slice/infoSlice";

function App() {
  // store의 state 불러오기
  const info = useSelector((state) => state.info);
  // dispatch 사용하기
  const dispatch = useDispatch();

  const [name, setName] = useState("홍길동");
  const [age, setAge] = useState(20);

  const handleInputName = (e) => {
    setName(e.target.value);
  };

  const handleInputAge = (e) => {
    setAge(e.target.value);
  };

  // dispatch를 통해 action을 store로 전달
  const submitName = () => {
    dispatch(changeName(name));
  };

  const submitAge = () => {
    dispatch(changeAge(age));
  };

  return (
    <div className="App" style={{ display: "flex", flexDirection: "column" }}>
      <div>{`현재 이름은 ${info.name} 입니다.`}</div>
      <div>{`현재 나이는 ${info.age}세 입니다.`}</div>
      <div>
        <label>
          이름
          <input onChange={handleInputName}></input>
          <button onClick={submitName}>이름 변경</button>
        </label>
      </div>
      <div>
        <label>
          나이
          <input type="number" onChange={handleInputAge}></input>
          <button onClick={submitAge}>나이 변경</button>
        </label>
      </div>
    </div>
  );
}

export default App;

 

4. 구현된 코드로 보기

함께 보면 좋은 글

2023.10.09 - [react/상태관리] - redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레거시)

 

redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레거시)

redux toolkit 없이 전역 상태 관리 하는 방법을 알아봅니다. 현재는 toolkit 사용을 권장하고 있어, 오늘날에 사용되는 코드는 아닙니다. redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레

ddmoonddmoon.tistory.com

 

 redux toolkit 없이 전역 상태 관리 하는 방법을 알아봅니다. 현재는 toolkit 사용을 권장하고 있어, 오늘날에 사용되는 코드는 아닙니다.

redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레거시)

 

 목차

 

1. redux란?

2. redux의 구성

3. 장점

4. 단점

5. 구현

6. 구현된 코드로 보기

 

1. redux란?

  • react에서 사용되는 전역 상태 관리 라이브러리
  • 기존의 하향식 전달에서 벗어나 어디서든 상태를 참조, 변경을 가능하게끔 함

2. redux의 구성

  • state
    • redux에서 관리하는 상태 정보

 

  • action
    • 상태를 변경하는 요청
    • 어떠한 상태 변경을 하겠다를 타입에 명시
    • ex) 이름을 변경시키겠다, 나이를 변경시키겠다

 

  • reducer
    • 이전 state와 action을 받아 새로운 상태를 반환하는 함수
    • 액션에 담긴 타입에 맞춰 로직 실행
    • 상태를 변경시키는 로직이 담겨 있음

 

  • store
    • state, action, reducer 모두를 관리하는 중앙 저장소
    • action을 reducer로 전달하여 상태 변경을 적용

 

  • dispatch
    • action을 store로 전달하는 메서드
redux 작동 과정

3. 장점

  • 쉬운 디버깅
    • redux devtools를 사용하면 디버깅이 쉬움

 

  • 높은 점유율
    • redux는 다른 상태 관리 라이브러리와 비교해 점유율이 높음
    • 따라서 관련 자료들을 쉽게 찾을 수 있음

 

  • middleware 지원
    • middleware는 reducer가 action을 처리하기 전에 추가적인 로직을 가능하게 해줌
    • 비동기 작업, 인증 등 추가적인 작업을 처리가능

 

4. 단점

  • boilerplate (작성해야 하는 코드가 많음)
    • redux를 사용하기 위해 기본적으로 작성해야 하는 코드가 많은 편
    • redux-toolkit 등의 라이브러리를 통해 코드를 줄일 수 있지만, 그럼에도 다른 상태 관리 라이브러리로 보다는 코드가 긴편

 

  • 비동기 작업 복잡
    • 비동기 작업을 처리하기 위해 Redux Thunk, Redux Saga 등 middleware를 사용할 수 있지만, 이 역시 다른 상태 관리 라이브러리 보다 사용법이 다소 복잡한 편

5. 구현

  • reducer 설치

 

npm i redux react-redux redux-devtools-extension

 

  • reducer를 작성
    • 초기 상태 값을 작성
    • reducer 내부에 각 액션에 따라 어떠한 로직을 실행할 지 작성
    • action을 작성, payload는 action의 parameter를 의미
    • 생성한 reducer와 action을 export

 

// store/reducers/infoReducer.js

// 기본 상태 값을 설정
const initialState = {
  name: "홍길동",
  age: 20,
};

// reducer를 작성
// 각 액션에 따라 어떠한 로직을 실행할 지 작성
const infoReducer = (state = initialState, action) => {
  switch (action.type) {
    case "CHANGENAME":
      return { ...state, name: action.payload };
    case "CHANGEAGE":
      return { ...state, age: action.payload };
    default:
      return state;
  }
};

// 액션 작성

// changeName 액션 작성
// payload는 action에 담긴 parameter를 의미
const changeName = (value) => ({
  type: "CHANGENAME",
  payload: value,
});

// changeAge 액션 작성
const changeAge = (value) => ({
  type: "CHANGEAGE",
  payload: value,
});

// 생성한 reducer와 action export
export { infoReducer, changeName, changeAge };

 

 

  • rootReducer 작성
    •  combineReducers를 통해 생성한 reducer를 모두 묶어줌
    • comibineReducers에서 reducer에 지정한 키를 통해 상태를 불러 올 수 있음 (useSelector 부분 참고)

 

// store/reducers/rootReducer.js

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

// 생성한 리듀서를 하나로 묶어 줌
const rootReducer = combineReducers({

// state에서 해당 상태를 불러올 때 state.info를 통해 접근할 수 있음
  info: infoReducer,
});

export default rootReducer;

 

 

  • store 작성
    • createStore은 현재 사용을 권장하지 않음. 현재 코드에서는 redux toolkit을 사용하지 않기에 사용
    • store에 rootReducer 추가
    • composeWithDevTools()를 적용하여 redux 개발자 도구 사용 가능

 

import { createStore } from "redux";
import rootReducer from "./reducers/rootReducer";
import { composeWithDevTools } from "redux-devtools-extension";

// store를 생성
// createStore은 현재 권장되지 않는 방법, 앞으로는 toolkit의 configureStore를 사용합시다.
// store에는 rootReducer를 넣어줌
// composeWithDevTools를 넣어 redux 스토어의 변화를 확인할 수 있음
const store = createStore(rootReducer, composeWithDevTools());

export default store;

 

  • redux를 사용하고자 하는 컴포넌트 최상단에 store 적용

 

// main.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store/store";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
  
    {/* redux를 이용하고자 하는 컴포넌트 최상단에 store를 적용 */}
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

 

  • redux 사용하기
    • useSelector로 store 상태 불러오기
    • useDispatch로 dispatch 사용하기
    • dispatch를 통해 action을 store로 전달하기

 

import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { changeAge, changeName } from "./store/reducers/infoReducer";

function App() {

  // useSelector를 통해 store의 상태를 불러올 수 있음
  // rootReducer의 할당한 키를 통해 불러올 수 있음
  const info = useSelector((state) => state.info);

  // useDispatch에 action을 이용하면 상태 변화 로직을 실행할 수 있음
  const dispatch = useDispatch();

  const [name, setName] = useState("홍길동");
  const [age, setAge] = useState(20);

  const handleInputName = (e) => {
    setName(e.target.value);
  };

  const handleInputAge = (e) => {
    setAge(e.target.value);
  };

  const submitName = () => {
  
    // action을 dispatch를 통해 store로 전달
    // changeName에 해당하는 상태 변화 로직 실행
    dispatch(changeName(name));
  };

  const submitAge = () => {
  
    // action을 dispatch를 통해 store로 전달
    // changeAge에 해당하는 상태 변화 로직 실행
    dispatch(changeAge(age));
  };

  return (
    <div className="App" style={{ display: "flex", flexDirection: "column" }}>
      <div>{`현재 이름은 ${info.name} 입니다.`}</div>
      <div>{`현재 나이는 ${info.age}세 입니다.`}</div>
      <div>
        <label>
          이름
          <input onChange={handleInputName} />
        </label>
        <button onClick={submitName}>이름 변경</button>
      </div>
      <div>
        <label>
          나이
          <input type="number" onChange={handleInputAge} />
        </label>
        <button onClick={submitAge}>나이 변경</button>
      </div>
    </div>
  );
}

export default App;

 

  • devtools 사용
    • chrome extension 에서 redux devtools 설치 
    • 현재 state와 실행 되었던 action 확인
     

redux devtools 설치

 

redux devtools 실행

 

좌측 action, 우측 state 확인

6. 구현된 코드로 보기

'react > 상태관리' 카테고리의 다른 글

redux toolkit으로 전역 상태 관리하기  (1) 2023.10.09
mobx 사용하기  (0) 2023.10.06

mobx는 react의 상태 관리 라이브러리 입니다. class 형태로 작성하여 프로퍼티, 메서드 형태로 상태를 관리 합니다.

mobx 사용하기

 

목차

 

1. mobx란?

2. 장점

3. 단점

4. 사용법

5. 구현된 코드로 보기

 

1. mobx란?

  • react 내에서 전역 상태 관리를 할 때에 사용하는 라이브러리
  • class로 만들어서 사용
  • 관리하는 상태 값은 클래스의 프로퍼티로, 상태를 변경하는 함수는 클래스의 메서드로 생성

2. 장점

  • 코드량이 적음(boilerlplate가 적음)
    • redux는 action, reducer, store 등 작성해야하는 코드가 많음
    • mobx는 class를 만들어 프로퍼티와 메서드를 생성해주면 됨

 

  • 비동기 처리 간편
    • 생성한 메서드에 async/await 키워드를 사용하면 됨

3. 단점

  • redux와 비교해 점유율이 낮은 편
    • 관련 자료를 찾을 경우 redux가 찾기가 편할 수 있으며, 레거시 코드들의 경우 redux를 사용했을 경우가 많음

 

압도적인 redux의 점유율

 

4. 사용법

  • mobx 설치
npm install --save mobx mobx-react-lite
  • store 생성
//store/counterStore.js

import { makeAutoObservable } from "mobx";

class CounterStore {
  count = 0;

  constructor() {
    makeAutoObservable(this);
  }

  increment() {
    this.count++;
  }

  decrement() {
    this.count--;
  }
}

export default new CounterStore();
  • observer를 통해 상태를 감지, 변경
import { observer } from "mobx-react-lite";
import counterStore from "./store/counterStore";
import "./App.css";
import Test from "./Test";

const App = observer(() => {   // observer로 사용.
  const handleIncrease = () => {
    counterStore.increment();   // class에서 지정한 메서드로 상태 변경
  };

  const handleDecrease = () => {
    counterStore.decrement();   
  };

  return (
    <div>
      <button onClick={handleDecrease}>-</button>
      <span>{counterStore.count}</span>   // class의 프로퍼티로 상태 불러오기
      <button onClick={handleIncrease}>+</button>

      <Test></Test>
    </div>
  );
});

export default App;

(사진) 카운터로 구현한 예시

5. 구현된 코드로 보기

+ Recent posts