Redux TypeScript

JH L·2022년 9월 18일
0

TypeScript로 redux, redux toolkit 사용하기

redux, typescript install

npm install @reduxjs/toolkit
npm install redux
npm install redux-thunk
npm install react-redux
npm install @types/node
npm install @types/react
npm install @types/react-dom
npm install @types/react-redux

store.ts 생성

import { configureStore, ThunkAction, Action } from '@redux/toolkit';
//import sliceReducer from '~/slice'

export const store = configureStore({
  reducer: {
    // name1: name1Reducer,
    // name2: name2Reducer,
    // slice: sliceReducer
  },
});

export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppThunk<ReturnType = void> = ThunkAction<
  ReturnType,
  RootState,
  unknown,
  Action<string>
>;

hooks.ts

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

index.tsx

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

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

slice.ts

import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { RootState, AppThunk } from '~/app/store';

export interface SliceState {
  a: number;
  b: string;
  c: 'x' | 'y' | 'z';
}

const initialState: SliceState = {
  a: 1;
  b: '1';
  c: 'x';
}

// 비동기 처리
export const asyncAction = createAsyncThunk(
  'name',
  async () => {
    const res = await axios.get(`${process.env.REACT_APP_URL}`, {
      withCredentials: true,
      headers: {
      'Authorization': `Bearer ${process.env.REACT_APP_TOKEN}`
      }
    })
  }
);

export const slice = createSlice({
  name: 'sliceName',
  initialState,
  reducers: {
    action1: (state, action: PayloadAction<string>) => {
      state.b = action.payload;
    },
    action2: (state, action: PayloadAction<number>) => {
      state.a = action.payload;
    }
  },
  extraReducers: (builder) => {
    builder
      .addCase(asyncAction.fulfilled, (state, action) => {
        state.c = action.payload;
      })
      .addCase(asyncAction.pending, (state, action) => {
        //
      })
      .addCase(asyncAction.rejected, (state, action) => {
        //
      })
  }
});

export const { action1, action2 } = slice.actions;

export const selectA = (state: RootState) => state.slice.a;
export const selectB = (state: RootState) => state.slice.b;

export const customThunk = (): AppThunk => (
  dispatch,
  getState
) => {
  const currentValue = selectA(getState());
  if (1) {
    dispatch(action1('2'));
  }
}

export default slice.reducer;

hooks.ts

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';

export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;

components.tsx

import { useAppSelector, useAppDispatch } from '~/hooks'
import { action1, asyncAction, selectA, custonThunk } from './slice'

function foo() {
  const dispatch = useAppDispatch();
  const valueA = useAppSelector(selectA);
  
  const handleClick = (str: string) => {
    dispatch(action1(str));
  }
  
  return (
    <div onClick={() => handleClick('click')}>click<div>
  );
}

export default foo;
profile
...

0개의 댓글