typesafe-action
이 라이브러리를 사용하면 타입스크립트를 사용할 때 액션생성함수와 리듀서를 더 깔끔하게 작성할 수 있게 된다.
// counter.tsx
import { createAction, ActionType, createReducer } from 'typesafe-actions';
const INCREASE = 'counter/INCREASE';
const DECREASE = 'counter/DECREASE';
const INCREASE_BY = 'counter/INCREASE_BY';
export const increase = createAction(INCREASE) ();
export const decrease = createAction(DECREASE) ();
export const increaseBy = createAction(INCREASE_BY)<number>();
type CounterState = {
count: number;
};
const initialState: CounterState = {
count: 0
}
const actions = { increase, decrease, increaseBy};
type CounterAction = ActionType<typeof actions>;
const counter = createReducer<CounterState, CounterAction>(initialState, {
[INCREASE] : (state) => ({ count: state.count + 1 }),
[DECREASE] : (state) => ({ count: state.count - 1 }),
[INCREASE_BY] : (state, action) => ({ count: state.count + action.payload})
});
//Reducer을 method chaining 방식으로도 지원한다 그에 대한 예시 밑에
// const counter = createReducer<CounterState, CounterAction>(initialState)
// .handleAction(INCREASE, state => { count: state.count + 1}))
// .handleAction(DECREASE, state => { count: state.count - 1}))
// .handleAction(INCREASE_BY, (state , action ) => ({
// count: state.action + action .payload
// }));
//이로 인해서 얻을 수 있는 장점은 액션의 문자열 타입 대신에 액션생성함수를 넣어도 작동한다는 것이다.
// 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};
// case INCREASE_BY:
// return {count: state.count + action.payload};
// default:
// return state;
// }
// }
export default counter;
//todos.ts
import { action, ActionType, createAction, createReducer} from 'typesafe-actions'
const ADD_TODO = 'todos/ADD_TODO' as const;
const TOGGLE_TODO = 'todos/TOGGLE_TODO' as const;
const REMOVE_TODO = 'todos/REMOVE_TODO' as const;
let nextId = 1;
export const addTodo = (text: string) => ({
type: ADD_TODO,
payload: {
id: nextId++,
text
}
});
export const toggleTodo = createAction(TOGGLE_TODO)<number>();
export const removeTodo = createAction(REMOVE_TODO)<number>();
const actions = {
addTodo,
toggleTodo,
removeTodo
};
type TodosAction = ActionType<typeof actions>;
export type Todo = {
id: number;
text: string;
done: boolean;
}
type TodosState = Todo [];
const initialState: TodosState = [];
const todos =createReducer<TodosState, TodosAction> (initialState, {
[ADD_TODO]: (state, action) => state.concat({
...action.payload,
done:false
}),
[TOGGLE_TODO]: (state, action) => state.map(
todo => todo.id === action.payload
? {...todo, done: !todo.done}
: todo
),
[REMOVE_TODO]: (state, action) => state.filter(
todo => todo.id !== action.payload
)
})
// function todos (state: TodoState = initialState,
// action: TodosAction):TodoState {
// switch(action.type) {
// case ADD_TODO:
// return state.concat({
// id: action.payload.id,
// text: action.payload.text,
// done: false
// });
// case TOGGLE_TODO:
// return state.map(todo => todo.id === action.payload ? {...todo, done: !todo.done} : todo
// );
// case REMOVE_TODO:
// return state.filter(todo => todo.id !== action.payload)
// default:
// return state;
// }
// }
export default todos;