TypeScript로 redux, redux toolkit 사용하기
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
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>
>;
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
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')
);
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;
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from './store';
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
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;