yarn add redux-actions
import {createACtion, handleActions} from 'redux-actions';
...
// 액션생성 함수
export const increase = createActions(INCREASE);
export const decrease = createActions(DECREASE);
// 리듀서함수 대체
const counter = handleActions(
{
[INCREASE] : (state, action) => ({ number : state.number + 1 }),
[DECREASE] : (state, action) => ({ number : state.number - 1 }),
},
initialState,
);
...
...
// 액션생성 함수
export const changeInput = createAction(CHANGE_INPUT, input => input);
let id = 3;
export const insert = createAction(INSERT, text => ({
id : id++,
text,
done : false,
})
);
export const toggle = createAction(TOGGLE, id => id)
export const remove = createAction(REMOVE, id => id)
// 리듀서함수 대체
const todos = handleActions(
{
[CHANGE_INPUT] : (state, action) => ({...state, action.payload}),
[INSERT] : (state, action) => ({
...state,
todos : state.todos.concat(action.payload),
}),
[TOGGLE] : (state, action) => ({
...state,
todos : state.todos.map(todo =>
todo.id === action.payload ? {...todos,, done : !todo.done} : todo,
),
}),
[REMOVE] : (state, action) => ({
...state,
todos : state.todos.filter(todo => todo.id !== action.payload)
}),
},
initialState,
)
...
...
const todos = handleActions({
[CHANGE_INPUT] : (state, {payload : input}) => ({...state, input}),
...
})
// 먼저 immer 설치해주고
// > yarn add immer
// module/todos.js
import {produce} from 'immer';
...
const todos = handleActions({
...
// TOGGLE 이외에는 기존 JS 코드가 더 간편
[TOGGLE] : (state, {payload : id}) =>
produce(state, draft => {
const todo = draft.todos.find(todo => todo.id === id);
todo.done = !todo.done;
}),
...
})
사용법
const result = useSelector(상태 선택 함수)
상태선택 함수는 mapStateToProps와 형태가 똑같음
사용법
const dispatch = useDispatch();
dispatch({type : 'ACION_TYPE'});
import {useSelector, useDispatch} from 'react-redux';
...
const CounterContainer = () => {
// useSelector로 상태 조회
const number = useSelector(state => state.counter.number);
// useDispatch로 액션 디스패치
const dispatch = useDispatch();
// 바로 디스패치(액션생성함수) 넣으면 재렌더링 시마다 함수 재생성
// useCallback으로 성능 최적화 권장
const onIncrease = useCallback(() => dispatch(increase()), [dispatch]);
const onDecrease = useCallback(() => dispatch(decrease()), [dispatch]);
return (
<Counter
number={number}
onIncrease={onIncrease}
onDecrease={onDecrease}
/>
)
};
export default CounterContainer;
// container/TodosContainer.js
...
const TodosContainer = () => {
const {input, todos} = useSelector(({todos}) => ({
input : todos.input,
todos : todos.todos,
}));
const dispatch = useDispatch();
const onChangeInput = useCallback(input => dispatch(changeInput(input)), [dispatch]);
const onInsert = useCallback(text => dispatch(insert(text)), [dispatch]);
const onToggle = useCallback(id => dispatch(toggle(id)), [dispatch]);
const onRemove = useCallback(id => dispatch(remove(id)), [dispatch]);
return (
<Todos
input = {input}
todos = {todos}
onChangeInput = {onChangeInput}
onInsert = {onInsert}
onToggle = {onToggle}
onRemove = {onRemove}
/>
)
}
export default TodosContainer;
// TodoContainer에 적용해보기
import { useActions } from "../lib/useActions";
const TodoContainer = () => {
...
const [onChangeInput, onInsert, onToggle, onRemove] = useActions(
[changeInput, insert, toggle, remove],
[]
);
return (
<Todos
input = {input}
todos = {todos}
onChangeInput = {onChangeInput}
onInsert = {onInsert}
onToggle = {onToggle}
onRemove = {onRemove}
/>
)
};
export default TodosContainer;
```
const store = useStore();
store.dispatch({type : 'SAMPLE_ACTION'});
store.getState();
```
뛰어난 글이네요, 감사합니다.