Hits bn

# 4장. redux 및 snippet 적용하기

# 1. sampleReducer 생성

자주 사용하는 ducks패턴을 적용한 redux reducer 형식을
snippets로 등록하기 위한 sampleReducer를 만든다.
/src/modules/sampleReducer.ts

import produce from "immer";
//import your data type

// 1. Action Type
const LOAD_DATA = "sample/LOAD_DATA";
const ADD_DATA = "sample/ADD_DATA";
const REMOVE_DATA = "sample/REMOVE_DATA";

// 2. Action Creator
// change type any to your data Type
export const LoadDataAction = (data: any[]) => ({
    type: LOAD_DATA,
    payload: data,
});
export const AddDataAction = (data: any) => ({ type: ADD_DATA, payload: data });
export const RemoveDataAction = (items: any[]) => ({
    type: REMOVE_DATA,
    payload: items,
});

// 3. return types
export type sampleActions =
    | ReturnType<typeof LoadDataAction>
    | ReturnType<typeof AddDataAction>
    | ReturnType<typeof RemoveDataAction>;

// 4.
interface sampleItem {
    //extends data type
    id: number;
}
// 5. State type
export interface sampleState {
    items: sampleItem[]; //any to your data Type
}

// 6. initial State
const initialState: sampleState = {
    items: [],
};

// 6. reducer
const sampleReducer = (
    state: sampleState = initialState,
    action: sampleActions
): sampleState => {
    switch (action.type) {
        case LOAD_DATA: {
            return produce(state, (draft) => {});
        }
        case ADD_DATA: {
            return produce(state, (draft) => {});
        }
        case REMOVE_DATA: {
            return produce(state, (draft) => {});
        }
        default: {
            return produce(state, (draft) => {});
        }
    }
};

export default sampleReducer;

# 2. redux reducer snippet 만들기

위 코드를 snippet generator에 넣고 "sample"이란 단어를 모두 ${TM_FILENAME_BASE}로 바꿔준다.
snippet generator (opens new window)

import produce from 'immer';
//import your data type

// 1. Action Type
const LOAD_DATA = '${TM_FILENAME_BASE}/LOAD_DATA';
const ADD_DATA = '${TM_FILENAME_BASE}/ADD_DATA';
const REMOVE_DATA = '${TM_FILENAME_BASE}/REMOVE_DATA';

// 2. Action Creator
// change type any to your data Type
export const LoadDataAction = (data: any[]) => ({ type: LOAD_DATA, payload: data });
export const AddDataAction = (data: any) => ({ type: ADD_DATA, payload: data });
export const RemoveDataAction = (items: any[]) => ({ type: REMOVE_DATA, payload: items });

// 3. return types
export type ${TM_FILENAME_BASE}Actions = ReturnType<typeof LoadDataAction> | ReturnType<typeof AddDataAction> | ReturnType<typeof RemoveDataAction>;

// 4.
interface ${TM_FILENAME_BASE}Item { //extends data type
    id: number;
}
// 5. State type
export interface ${TM_FILENAME_BASE}State {
    items: ${TM_FILENAME_BASE}Item[];  //any to your data Type
}

// 6. initial State
const initialState: ${TM_FILENAME_BASE}State = {
    items: []
};

// 6. reducer
const ${TM_FILENAME_BASE}Reducer = (state: ${TM_FILENAME_BASE}State = initialState, action: ${TM_FILENAME_BASE}Actions): ${TM_FILENAME_BASE}State => {
    switch (action.type) {
        case LOAD_DATA: {
            return produce(state, draft => { });
        }
        case ADD_DATA: {
            return produce(state, draft => { });
        }
        case REMOVE_DATA: {
            return produce(state, draft => { });
        }
        default: {
            return produce(state, draft => { });
        }
    }
}

export default ${TM_FILENAME_BASE}Reducer;

Description에는 snippet 이름을, Tab Trigger에는 사용할 snippet 단축이름을 입력한다.
본인은 ReduxReducerDucksrrd를 입력했다.

생성된 snippet 정보는 다음과 같다.

"ReduxReducerDucks": {
  "prefix": "rrd",
  "body": [
    "import produce from 'immer';",
    "//import your data type",
    "",
    "// 1. Action Type",
    "const LOAD_DATA = '${TM_FILENAME_BASE}/LOAD_DATA';",
    "const ADD_DATA = '${TM_FILENAME_BASE}/ADD_DATA';",
    "const REMOVE_DATA = '${TM_FILENAME_BASE}/REMOVE_DATA';",
    "",
    "// 2. Action Creator",
    "// change type any to your data Type",
    "export const LoadDataAction = (data: any[]) => ({ type: LOAD_DATA, payload: data });",
    "export const AddDataAction = (data: any) => ({ type: ADD_DATA, payload: data });",
    "export const RemoveDataAction = (items: any[]) => ({ type: REMOVE_DATA, payload: items });",
    "",
    "// 3. return types",
    "export type ${TM_FILENAME_BASE}Actions = ReturnType<typeof LoadDataAction> | ReturnType<typeof AddDataAction> | ReturnType<typeof RemoveDataAction>;",
    "",
    "// 4.",
    "interface ${TM_FILENAME_BASE}Item { //extends data type",
    "    id: number;",
    "}",
    "// 5. State type",
    "export interface ${TM_FILENAME_BASE}State {",
    "    items: ${TM_FILENAME_BASE}Item[];  //any to your data Type",
    "}",
    "",
    "// 6. initial State",
    "const initialState: ${TM_FILENAME_BASE}State = {",
    "    items: []",
    "};",
    "",
    "// 6. reducer",
    "const ${TM_FILENAME_BASE}Reducer = (state: ${TM_FILENAME_BASE}State = initialState, action: ${TM_FILENAME_BASE}Actions): ${TM_FILENAME_BASE}State => {",
    "    switch (action.type) {",
    "        case LOAD_DATA: {",
    "            return produce(state, draft => { });",
    "        }",
    "        case ADD_DATA: {",
    "            return produce(state, draft => { });",
    "        }",
    "        case REMOVE_DATA: {",
    "            return produce(state, draft => { });",
    "        }",
    "        default: {",
    "            return produce(state, draft => { });",
    "        }",
    "    }",
    "}",
    "",
    "export default ${TM_FILENAME_BASE}Reducer;"
  ],
  "description": "ReduxReducerDucks"
}

# 3. vscode에 snippet 등록

  • 파일 > 기본설정 > 사용자 코드조각 > typescript 선택하고 위의 snippet json을 붙여넣는다.

  • test.ts 파일을 생성하고
    snippet key로 설정한 rrd를 입력하여 redux reducer 자동완성이 잘 되는지 확인한다.

  • 파일이름인 test를 갖는 ducks 패턴이 적용된 redux reducer가 바로 생성되었다.

# 4. redux rootReducer 생성

/src/modules 하위에 index.ts 파일을 생성한다.
생성후에 위에서 sample로 만든 reducer를 추가한다.

import sampleReducer, { sampleState } from "./sampleReducer";
import { combineReducers } from "redux";

export interface StoreState {
    //reducer 추가시 아래 형태로 추가
    //reducer : reducerState
    sampleReducer: sampleState;
}

const rootReducer = combineReducers<StoreState>({
    //interface에 추가한 reducer 설정
    sampleReducer,
});

export default rootReducer;
export type RootState = ReturnType<typeof rootReducer>;

# 5. rootReducer 등록

/src/index.tsx에 rootReducer를 createStore를 통해 store를 만들고 provider에 등록한다.

index.tsx

import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { createStore } from "redux";
import App from "./App";
import rootReducer from "./modules";

const store = createStore(rootReducer);

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <App />
        </Provider>
    </React.StrictMode>,
    document.getElementById("root")
);

redux와 redux reducer snippets 적용까지 끝냈다.


Github Link : react-typescript-project-starter (opens new window)


Last Updated: 3/31/2022, 5:42:06 PM