[React/TS] React + TypeScript 사용할 때 알아야할 점2 : Redux toolkit

qwe8851·2022년 12월 12일
0

🙆‍♂️ TypeScript

목록 보기
7/9

redux는
1. state를 한곳에 관리할 수 있어서 compoent들이 props없이 state를 다루기 쉽고
2. 수정방법을 미리 reducer라는 함수로 정의해놔서 state 수정 시 발생하는 버그를 줄일 수 있음

  • redux 공식 toolkit 라이브러리를 써서 코드짜는 신규방식 redux
  • 예전처럼 if문 switch문 쓰는 전통방식 redux
    둘 다 타입지정하는 방법에 대해 알아보자




🤔 전통방식 redux

✨ 전통 - state와 reducer만들 때 타입 지정 필요

redux 설치 : npm install redux react-redux
redux는 type정의가 미리 잘 되어있어 그냥 설치만 하면 됨.

일단 예제로 <button>을 누르면 state가 +1, -1되는 예제를 작성해보겠음

그러려면
1. state가 필요하고,
2. +와 -하는 방법을 정의해둔 reducer가 필요할 듯

파일을 여러개로 나누면 이해가 어려우니 보기쉽게 index.ts에 필요한 모든 코드를 적어보겠음.

(index.ts)

import { Provider } from 'react-redux';
import { createStore } from 'redux';

interface Counter {
  count : number
}

const 초기값 :Counter  = { count: 0 };

function reducer(state = 초기값, action :any) {
  if (action.type === '증가') {
    return { count : state.count + 1 }
  } else if (action.type === '감소'){
    return { count : state.count - 1 }
  } else {
    return initialState
  }
}

const store = createStore(reducer);

// store의 타입 미리 export 해두기 
export type RootState = ReturnType<typeof store.getState>

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>,
  document.getElementById('root')
) 
  1. initialState = {count : 0 }이렇게 생긴 state 초기값 설정
  2. function reducer를 만들어 state가 변경되는 방법을 미리 정의해둠
    (변경방법은 1. 증가 2. 감소두개)
  3. createStore이런 나머지는 자잘한 기본 셋팅 문법

지금 보이는 변수와 함수에 타입지정을 하면 됨
그래서 redux쓸 때는 똑같이 state초기값과 reducer함수의 타입지정을 잘하면 됨.

1) 초기값 변수 오른쪽에 타입지정

2) reducer 함수는 state, action이 이름의 파라미터 2개 타입저정

state는 사실 타입지정이 필요 없음
초기값넣으면 타입지정이 잘 됨

action은 나중에 dispatch날릴 때 집어넣는 object자료와 똑같이 생겨야 함
그래서 그거 그대로 타입지정을 해주면 되는데 대부분 {type:string, payload:number}이런식으로 생겼음.
위에선 any라고 대충 넣음

3) 마지막으로 심심하면 reducer함수의 return타입도 지정해보기

어떤 걸 return 해줘야 할지 적어두면 됨
딱 봐도 초기값이랑 유사하게 생기면 될 듯

그리고 reducer 타입지정은 전부 reducer 안의 코드들을 잘못 써서 생기는 버그를 약간 방지하는 요오임.
App.tsx같은데서 dispatch()를 잘 쓰냐 못 쓰냐 캐치해 주지는 않음




✨ 전통 - state를 꺼낼 때

redux에 있던 state를 가져오려면
mapStateToProps도 있지만 useSelector훅을 쓰면 간단하게 가져올 수 있음

그리고 state를 변경하려면 useDispatch훅을 쓰면 dispatch를 간단하게 날릴 수 있음


import React from 'react';
import { useDispatch, useSelector } from 'react-redux'
import { Dispatch } from 'redux'
import {RootState} from './index'

function App() {
  const 꺼내온거 = useSelector( (state :RootState) => state );
  const dispatch :Dispatch = useDispatch();

  return (
    <div className="App">
      { 꺼내온거.count }
      <button onClick={()=>{dispatch({type : '증가'})}}>버튼</button>
      <Profile name="kim"></Profile>
    </div>
  );
} 
  1. useSelector를 쓰면 redux에 있던 state를 빼오기 쉬움. 안에 콜백함수넣으면 거기 있던 파라미터가 그대로 state임
  2. useDispath를 쓰면 redux로 수정요청을 날릴 수 있음. type을 잘 기입하면 미리 정의해뒀던 수정방법이 동작함
    위에선 버튼을 누르면 증가하라고 해놨음.

타입지정은 그냥

1) useSelector()안에 파라미터에 타입지정

state가 어떻게 생겼는지 파악한 다음 타입을 알아서 손수 지정해주거나
귀찮으면 index.ts안에 타입을 exprot해서 가져와도 됨

index.ts안에 있던 exprot type RootState = ReturnType<typeof store.getState> ← 이 코드가 store의 타입을 미리 export해두는 방법임

2) useDispatch도 타입지정하면 좋음

import { Dispatch } from 'redux'이렇게 타입을 가져와서
const dispatch : Dispatch이렇게 쓰면 됨
그럼 dispatch날릴 때 안에 파라미터 안쓰면 에러내줌




🤔 신규방식 redux

✨ 신규 - state와 reducer 만들 때 타입지정 필요

신식 redux를 사용하고 싶으면 redux, react-redux에 이어

npm install @reduxjs/toolkit 

@reduxjs/toolkit 라이브러리를 추가로 설치해주면 됨.
그럼 이제 조금 더 깔끔하게 코드를 짤 수 있음.

위와 같은 예제로 <button>버튼을 누르면 state가 +1, -1되는 예제를 만들어보겠음
index.ts에 필요한 모든 코드를 적었음

(index.ts)

import { createSlice, configureStore } from '@reduxjs/toolkit';
import { Provider } from 'react-redux';

const 초기값 = { count: 0, user : 'kim' };

const counterSlice = createSlice({
  name: 'counter',
  initialState : 초기값,
  reducers: {
    increment (state){
      state.count += 1
    },
    decrement (state){
      state.count -= 1
    },
    incrementByAmount (state, action :any){
      state.count += action.payload
    }
  }
})

let store = configureStore({
  reducer: {
    counter1 : counterSlice.reducer
  }
})

//state 타입을 export 해두는건데 나중에 쓸 데가 있음
export type RootState = ReturnType<typeof store.getState>

//수정방법 만든거 export
export let {increment, decrement, incrementByAmount} = counterSlice.actions

그리고 하단에 <Provider store = { store }>이런 코드를 추가해주면 끄읏-

  1. createSlice()로 slice를 만들어줌
    slice는 state와 reducer를 합쳐놓은 새로운 뭉텅이라고 보면 됨.
  2. slice안에는 slice이름, state초기값, reducer가 정확한 이름으로 들어가야 함. 맘대로작명불가!!!!!
  3. state는 그냥 맘대로 만들면 되고, reducer는 함수 형태로 만들어줘야 함.
    첫번째 파라미터는 state, 두번째는 action이 자동으로 부여됨.
  4. 다 만든 것들은 configureStore안에 등록
  5. 내가 만들어둔 reducer를 쓰고 싶음 reducer안에 함수명을 exprot
  6. 나머지는 필요없는 셋팅문법

타입지정은

1) state초기값 타입지정은 알아서

2) reducer안에 action 파라미터 타입지정 필요

3) 나머지는 타입지정 필요 X (자동으로 됨)


action 타입지정은 방법이 따로 있는데

import { createSlice, PayloadAction } from '@reduxjs/toolkit'

(상단 생략)
  incrementByAmount (state, action: PayloadAction<number>){
      state.value += action.payload
  },

위처럼 타입지정을 하라고 권장함
나중에 dispatch할 때 보내는 데이터가 있으면 그걸 payload라고 부르는데,
그 자료의 타입을 <>안에 집어넣어서 타입지정하라는 소리임
문자를 payload로 보낼거면 string을 집어넣고~ 이런식임




✨ 신규 - state를 꺼낼 때

import { useDispatch, useSelector } from 'react-redux'
import {RootState, increment} from './index'

function App() {

  const 꺼내온거 = useSelector( (state :RootState) => state);
  const dispatch = useDispatch();

  return (
    <div className="App">
      {꺼내온거.counter1.count}
      <button onClick={()=>{dispatch(increment())}}>버튼</button>
    </div>
  );
} 
  1. useSelector함수를 쓰면 state를 쉽게 꺼낼 수 있음.
    쓰는 법은 안에 콜백함수()=>{}하나를 집어넣으면 되는데 그 함수의 첫 파라미터는 항상 state가 됨.
  2. useDispatch함수를 쓰면 쉽게 수정요청을 날릴 수 있음.

타입지정은 state와 dispatch안에 해주면 됨

1) useSelector()안의 파라미터에 타입지정

2) useDispatch()사용할 때 타입지정 가능

공식문서에서는
index.ts에서 export type AppDispatch = typeof store.dispatch해두고
App.tsx에서 import해와서 useDispatch<AppDispatch>()이렇게 타입지정하라고 되어있긴 함
귀찮으면 예전 방식으로 사용해도 무관

profile
FrontEnd Developer with React, TypeScript

0개의 댓글