원본 state를 직접 수정하지 않기!
redux store 를 사용하면 주의할 점은 원본 데이터를 변경하지 않아야한다는 것이다.
action을 reducer에 보내주어 새로운 state에 기존 state값을 복사하고 새로운 state 값을 변경하여 새로운 스테이트를 반환함 으로써 이전 state에 덮어씌여지도록 한다.
npm i @reduxjs/toolkit
/store/index.js
import { configureStore, createSlice } from "@reduxjs/toolkit";
const initialState = { counter: 0, showCounter: true };
// reducer 만들기! => createSlice() 사용
const counterSlice = createSlice({
name: "counter",
initialState,
reducers: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
},
increase(state, action) {
state.counter = state.counter + action.payload;
},
toggle(state) {
state.showCounter = !state.showCounter;
},
},
});
// Action creator 만들기
export const counterActions = counterSlice.actions;
// => 기존에 액션을 사용하는 것 처럼 바꿔 준다.
// counterSlice.actions.increment = {type: 'increment'};
// export 해서 action을 사용할때 import 해서 사용한다.
// dispatch(counterActions.increment()) 와 같이 사용
// counterActions.increase(10) 과 같이 인자를 넣으면
// {type: 'increase', payload: 10 } 으로 action을 만들어 보낸다.
// configureStore() 를 사용하여 store 만들기
// 리듀서는 한개로 만들어져야 하는데 관리가 쉽도록 여러개의 slice 만든다.
// 이런 여러개의 리듀서 slice를 한개로 묶어 하나의 리듀서로 만들어 사용하도록 해준다.
// 인자로 {reducer: {count: couterSlice.reducer, anything: anythingSlice.reducer}}
const store = configureStore({ reducer: counterSlice.reducer });
export default store;
Counter.js
import classes from "./Counter.module.css";
import { useDispatch, useSelector } from "react-redux";
// action creator 를 import 하여 사용한다.
import { counterActions } from "../store";
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const show = useSelector((state) => state.showCounter);
const incrementHandler = () => {
dispatch(counterActions.increment());
};
const increaseHandler = () => {
dispatch(counterActions.increase(10));
};
const decrementHandler = () => {
dispatch(counterActions.decrement());
};
const toggleCounterHandler = () => {
dispatch(counterActions.toggle());
};
return (
<main className={classes.counter}>
<h1>Redux Counter</h1>
{show && <div className={classes.value}>{counter}</div>}
<div>
<button onClick={incrementHandler}>Increment</button>
<button onClick={increaseHandler}>Increase+5</button>
<button onClick={decrementHandler}>Descrement</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
export default Counter;