redux-toolkit(RTK)는 이러한 문제점을 개선시켰다.
configureStore()
createSlice()
1) store 폴더에 store.js 파일을 생성한다.
import { configureStore } from "@reduxjs/toolkit";
const store = configureStore({
reducer: {},
});
export default store;
2) index.js에서 App 컴포넌트를 Provider로 감싸고 store prop을 전달한다.
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";import { createSlice } from "@reduxjs/toolkit";
import store from "./store/store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
3) counterSlice.js를 만든다.
import { createSlice } from "@reduxjs/toolkit";
// 초기값 생성
const initialState = {
value: 0,
};
const counterSlice = createSlice({
name: "counter",
initialState,
reducers: {
PLUS_ONE: (state) => {
state.value += 1;
},
MINUS_ONE: (state) => {
state.value -= 1;
},
PLUS_AMOUNT: (state, action) => {
state.value += action.payload;
},
},
});
// Counter.js에서 dispatch()하기 위해 actions를 export
export const { PLUS_ONE, MINUS_ONE, PLUS_AMOUNT } = counterSlice.actions;
// store.js의 reducer에 작성하기 위해 reducer를 export
export default counterSlice.reducer;
4) store.js에서 만든 reducer를 작성한다.
import { configureStore } from "@reduxjs/toolkit";
// counterSlice.js에서 reducer를 default로 export했으므로 원하는 이름으로 import 할 수 있다.
import counterReducer from "../reducer/counterSlice.js";
const store = configureStore({
reducer: {
counter: counterReducer,
},
});
export default store;
5) 만든 리듀서를 사용할 Counter.js를 작성한다.
import { useSelector, useDispatch } from "react-redux";
// counterSlice에서 name export한 actino들을 import한다.
import { PLUS_ONE, MINUS_ONE, PLUS_AMOUNT } from "../reducer/counterSlice";
const Counter = () => {
const count = useSelector((state) => state.counter.value);
const dispatch = useDispatch();
return (
<div>
<h1>현재 count 값 : {count}</h1>
<button onClick={() => dispatch(PLUS_ONE())}>+1</button>
<button onClick={() => dispatch(MINUS_ONE())}>-1</button>
<button onClick={() => dispatch(PLUS_AMOUNT(5))}>+5</button>
</div>
);
};
export default Counter;
const store = configureStore({
reducer: {
countcount: counterReducer,
},
});
6) App.js에 Counter 컴포넌트를 추가한다.
import Counter from "./counter/Counter";
function App() {
return (
<div>
<Counter />
</div>
);
}
export default App;
7) counter는 완성되었다.
1) 앞서 초기 설정은 다 되어 있으므로 reducer를 추가하기만 하면 된다.
2) reducer폴더에 mangeSlicer.js파일을 생성한다.
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
name: ["Kim", "Lee", "Park"],
};
const manageSlicer = createSlice({
name: "mange",
initialState,
reducers: {
ADD_NAME: (state, action) => {
state.name.push(action.payload);
},
DELETE_NAME: (state, action) => {
const newName = state.name.filter((name) => name !== "Kim");
state.name = newName;
},
},
});
export const { ADD_NAME, DELETE_NAME } = manageSlicer.actions;
export default manageSlicer.reducer;
3) store.js에 새로 만든 리듀서를 추가한다.
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "../reducer/counterSlice";
import manageReducer from "../reducer/manageSlicer";
const store = configureStore({
reducer: {
counter: counterReducer,
// 새로만든 reducer 추가
manager: manageReducer,
},
});
export default store;
4) manage 폴더에 Manager.js 파일을 생성한다.
import { useSelector, useDispatch } from "react-redux";
import { ADD_NAME, DELETE_NAME } from "../reducer/manageSlicer";
const Manager = () => {
const name = useSelector((state) => state.manager.name);
const dispatch = useDispatch();
return (
<div>
<br />
<br />
<br />
{name.map((name) => {
return <span key={name}>{name} </span>;
})}
<div>
<button onClick={() => dispatch(DELETE_NAME("Kim"))}>Delete Kim</button>
<button onClick={() => dispatch(ADD_NAME("John"))}>Add John</button>
</div>
</div>
);
};
export default Manager;
5) App.js에 새로만든 Manager 컴포넌트를 추가한다.
App.js에 새로만든 Manager 컴포넌트를 추가한다.
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
// 기존 상태를 변화시키면 value를 return할 필요가 없다.
todoAdded(state, action) {
state.push(action.payload)
},
}
})
const todosSlice = createSlice({
name: 'todos',
initialState: [],
reducers: {
todoDeleted(state, action.payload) {
// 새 배열을 immutable하게 만들면 return 해야함
return state.filter(todo => todo.id !== action.payload)
}
}
})
const todosSlice = createSlice({
name: 'todos',
initialState: {todos: [], status: 'idle'}
reducers: {
todoDeleted(state, action.payload) {
// 새 배열을 immutable하게 만들고
const newTodos = state.todos.filter(todo => todo.id !== action.payload)
// mutate를 통해 기존 상태에 새 배열을 저장한다.
state.todos = newTodos
}
}
})
묵시적 반환 : 화살표 함수에서 중괄호(curly braces)를 생략하고 reutrn을 생략시킨 후 반환시키는 방법
따라서 화살표 함수에서 해당 rule을 지킬 수 있는 두 가지 방법이 있다.
1) 묵시적 반환시에 앞에 void 키워드를 넣는법
fixedReducer1: (state, action) => void state.push(action.payload),
2) 중괄호(curly braces)를 사용해 함수의 body를 만들기 -> 이 때 return은 하지 않아도 된다.
fixedReducer2: (state, action) => {
state.push(action.payload)
},