Redux toolkit이란?

오유진·2023년 5월 4일
0

React

목록 보기
6/6

Redux란?

  • Redux는 JavaScript 애플리케이션에서 상태(state)를 관리하기 위한 예측 가능한(stateful) 컨테이너이다. Redux는 React, Angular, Vue.js 같은 뷰(View) 라이브러리와 함께 사용할 수 있으며, React와 가장 잘 맞는다.
  • 원래는 개발자가 쉽게 이해할수있고 간편한 Recoil을 사용했지만, 회사에서 Redux를 사용해서 기본 개념을 이해하기 위해 작성했다.

Redux toolkit이란?

  • Redux Toolkit은 Redux의 공식적인 유틸리티 라이브러리로, Redux를 사용하여 보다 쉽게 상태 관리를 할 수 있도록 만든 라이브러리이다. Redux Toolkit은 코드량을 줄이고 가독성을 높이며 성능을 개선하는 다양한 기능을 제공한다.
  • Redux Toolkit은 또한 Immer 라이브러리를 내부적으로 사용하여 불변성을 유지하면서 상태를 업데이트할 수 있는 produce 함수를 제공합니다. 이를 통해 상태를 업데이트하는 코드를 간결하게 작성할 수 있습니다.

예제

세팅

  • Redux Toolkit은 createSliceconfigureStore 함수를 제공하여 보일러 플레이트 코드를 줄일 수 있다. createSlice 함수는 Reducer 함수와 Action Creator 함수를 하나의 객체로 묶어주어 보다 간결한 코드를 작성할 수 있게 해주며, configureStore 함수는 Redux의 store를 생성하는데 사용된다.

  • createSlice를 사용하여 Reducer 함수와 Action Creator 함수를 하나의 객체로 만들면, 해당 Reducer 함수의 동작을 변경할 때 모든 Action Creator 함수를 수정하지 않아도 된다. 또한, configureStore 함수를 사용하면 Redux store를 생성하면서 Redux DevTools Extension과 같은 미들웨어를 쉽게 추가할 수 있다.

//counterReducer.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

interface ICounterState {
  value: number;
}

const counterInitialState: ICounterState = {
  value: 0,
};

const counterSlice = createSlice({
  name: "counter",
  initialState: counterInitialState,
  reducers: {
    increment: (state) => {
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    incrementByAmount: (state, action: PayloadAction<number>) => {
      state.value += action.payload;
    },
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;
//authReducer.ts
import { createSlice } from "@reduxjs/toolkit";

interface IAuthState {
  isLoggedIn: boolean;
}

const authInitialState: IAuthState = {
  isLoggedIn: false,
};

const authSlice = createSlice({
  name: "auth",
  initialState: authInitialState,
  reducers: {
    login: (state) => {
      state.isLoggedIn = true;
    },
    logout: (state) => {
      state.isLoggedIn = false;
    },
  },
});

export const { login, logout } = authSlice.actions;
export default authSlice.reducer;
  • 위 코드에서는 createSlice 함수를 사용하여 counterauth 두 개의 slice를 생성하였습니다. 각각 increment, decrement, incrementByAmountlogin, logout Action Creator 함수를 가지고 있다.
//store.ts
import { configureStore } from "@reduxjs/toolkit";
import authReducer from "./reducers/authReducer";
import counterReducer from "./reducers/counterReducer";

export const store = configureStore({
  reducer: {
    auth: authReducer,
    counter: counterReducer,
  },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
  • configureStore 함수를 사용하여 Redux store를 생성하고 reducer를 등록한다.
  • reducer 속성은 객체이며, 앱에서 사용할 각 reducer를 등록한다.
  • 여기서는 위에서 만든 authReducercounterReducer를 등록하여 store에 저장하였다.
    이제 이 store는 컴포넌트에서 useSelector를 사용하여 Redux store의 값을 읽어올 수 있고, useDispatch를 사용하여 action을 dispatch 할 수 있다. 또한, RootState 타입과 AppDispatch 타입을 정의하여 타입 안정성을 높일 수 있다.

사용

//index.tsx
import Auth from "@/components/Auth";
import Counter from "@/components/Counter";
import { RootState } from "@/slices/store";
import { useSelector } from "react-redux";

export default function Home() {
  const isAuthenticated = useSelector(
    (state: RootState) => state.auth.isLoggedIn
  );
  const count = useSelector((state: RootState) => state.counter.value);
  return (
    <>
      <div>
        <h1>Redux Test</h1>
        
        <Auth />
        <Counter />
        
        <h1>전역 상태 테스트</h1>
        <h1>auth : {isAuthenticated ? "login" : "logout"}</h1>
        <h1>count : {count}</h1>
      </div>
    </>
  );
}
  • useSelector 훅을 이용하여 authcounter 상태를 가져온다. 이제 Auth 컴포넌트와 Counter 컴포넌트에서도 마찬가지로 useSelector를 사용하여 상태를 가져올 수 있다.
//Auth.tsx
import { login, logout } from "@/slices/reducers/authReducer";
import { RootState } from "@/slices/store";
import { useDispatch, useSelector } from "react-redux";

export default function Auth() {
  const isAuthenticated = useSelector(
    (state: RootState) => state.auth.isLoggedIn
  );
  const dispatch = useDispatch();

  const handleLoginToggle = () => {
    if (isAuthenticated) {
      dispatch(logout());
    } else {
      dispatch(login());
    }
  };

  return (
    <>
      <h1>Auth.tsx</h1>
      <h1>{isAuthenticated ? "Logged In" : "Not Logged In"}</h1>
      <h1 onClick={handleLoginToggle}>
        Log In Toggle
      </h1>
    </>
  );
}
//Counter.tsx
import { decrement, increment } from "@/slices/reducers/counterReducer";
import { RootState } from "@/slices/store";
import { useDispatch, useSelector } from "react-redux";

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

  const handleIncrement = () => {
    dispatch(increment());
  };
  const handleDecrement = () => {
    dispatch(decrement());
  };

  return (
    <>
      <h1>Counter.tsx</h1>
      <h1 onClick={handleIncrement}>
        INCREMENT
      </h1>
      <h1>number : {count}</h1>
      <h1 onClick={handleDecrement}>
        DECREMENT
      </h1>
    </>
  );
}
  • useDispatch 훅을 이용하여 Reucer에서 만든 action을 준다.

결과

  • Recoil 보다 한번에 이해하기 쉽진 않지만, 개념만 알고있다면 넘어가기 어렵진 않은것같다.

0개의 댓글