React-Native Redux + TypeScript
포스트
취소

React-Native Redux + TypeScript

안녕하세요. Narvis2 입니다.
이번시간에는 ReduxTypeScript와 함께 사용하는 법에 대하여 간단한 예제를 통하여 알아보도록 하겠습니다.

🍀 Redux + TypeScript

  • Redux + TypeScript 적용 👉 yarn add redux react-redux @types/react-redux

    1️⃣ 예제 ) Redux Module 작성 👇

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    
    /**
     * ✅ Action Type
     * as const 👉 나중에 Action 객체를 만들게 action.type 의 값을 추론하는 과정에서
     * action.type 이 string 으로 추론되지 않고 'INCREASE'와 같이 실제 문자열 값으로 추론 되도록 해줌
     */
    const INCREASE = "INCREASE" as const;
    const DECREASE = "DECREASE" as const;
    
    // ✅ Action 생성 함수
    export const increase = () => ({ type: INCREASE });
    export const decrease = () => ({ type: DECREASE });
    
    /**
     * ✅ 모든 Action 객체들에 대한 타입을 준비
     * ReturnType<typeof _____> 👉 특정 함수의 반환값을 추론해줌
     * Action Type 을 선언 할 떄 as const 를 하지 않으면 이 부분이 제대로 작동하지 않음
     */
    type CounterAction =
      | ReturnType<typeof increase>
      | ReturnType<typeof decrease>;
    
    // ✅ 이 리덕스 모듈에서 관리 할 State의 Type을 선언
    type CounterState = {
      count: number;
    };
    
    // ✅ 초깃값 (상태가 객체가 아니라 그냥 숫자여도 상관 없음)
    const initialState: CounterState = {
      count: 0,
    };
    
    /**
     * ✅ Reducer를 작성
     * Reducer 에서는 state 와 함수의 반환값이 일치하도록 작성해야함
     * Action 에서는 CounterAction 을 타입으로 설정
     */
    export default function counter(
      state: CounterState = initialState,
      action: CounterAction
    ): CounterState {
      switch (action.type) {
        case "INCREASE":
          return { count: state.count + 1 };
        case "DECREASE":
          return { count: state.count - 1 };
        default:
          return state;
      }
    }
    

    2️⃣ 예제) Root Reducer 작성 👇

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    import { combineReducers } from "redux";
    import counter from "./counter";
    
    // ✅ Root Reducer 생성
    const rootReducer = combineReducers({ counter });
    
    export default rootReducer;
    
    /**
     * Root Reducer 의 반환값을 유추해줌
     * 추후 이 타입을 컨테이너 Component에서 불러와서 사용해야 하므로 내보냄
     */
    export type RootState = ReturnType<typeof rootReducer>;
    

    3️⃣ 예제 ) useSelector, useDispatch 사용 👇

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    
    import React from "react";
    import Counter from "./Counter";
    import { RootState } from "../modules";
    import { useSelector, useDispatch } from "react-redux";
    import { increase, decrease } from "../modules/counter";
    
    const CounterContainer = () => {
      /**
       * ✅ 현재 상태를 조회
       * 상태를 조회할 때는 state의 타입을 RootState로 지정해야함
       */
      const counter = useSelector((state: RootState) => state.counter);
      // Dispatch 함수를 가져옴 (action을 발생시켜 상태를 업데이트)
      const dispatch = useDispatch();
    
      function onIncrease() {
        dispatch(increase());
      }
    
      function onDecrease() {
        dispatch(decrease());
      }
    
      const props = {
        count: counter.count,
        onIncrease,
        onDecrease,
      };
    
      return <Counter {...props} />;
    };
    
    export default CounterContainer;
    

    4️⃣ 예제 ) Counter.tsx 👇

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    
    import React from "react";
    import { Pressable, Text, View } from "react-native";
    
    type CounterProps = {
      count: number;
      onIncrease: () => void;
      onDecrease: () => void;
    };
    
    const Counter = ({ count, onIncrease, onDecrease }: CounterProps) => {
      return (
        <View
          style=
        >
          <Text style=>{count}</Text>
          <Pressable onPress={onIncrease} style=>
            <Text>{+1}</Text>
          </Pressable>
          <Pressable onPress={onDecrease} style=>
            <Text>{-1}</Text>
          </Pressable>
        </View>
      );
    };
    
    export default Counter;
    

    5️⃣ 예제 ) Provier를 사용하여 App.tsx에 적용 👇

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    import { Provider } from "react-redux";
    import { createStore } from "redux";
    import CounterContainer from "./src/components/CounterContainer";
    import rootReducer from "./src/modules";
    
    const store = createStore(rootReducer);
    
    const App = () => {
      const isDarkMode = useColorScheme() === "dark";
    
      const backgroundStyle = {
        backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
      };
    
      return (
        <Provider store={store}>
          <SafeAreaView style={backgroundStyle}>
            <CounterContainer />
          </SafeAreaView>
        </Provider>
      );
    };
    
    export default App;
    
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.