
내가 보려고 정리한 상태관리를 위한 공부 했다.
ReduxcreateStore subscribe getState dispatch
상태관리란 ?
👉🏻 프로그램이 동작하는데 필요한 데이터를 체계적으로 분리해주는 것.
Redux자체는 React와 무관하다.Javascript로 된 프로젝트라면 어디서든 사용할 수 있다.Redux를 React에서 사용하려면 어려운 점이 많다.React-Redux이다.React-Rduxconnect useDispatch useSelector
이 도구를 사용하면
React와Redux를 통합할 수 있다.
그럼에도 불구하고 Redux를 이용하는데에 많은 문제점들이 있다.
이 문제점을 해결하는데에 사용하는 도구가 바로 Redux-toolkit이다.
먼저, 예제를 통해 어떻게 간편해 지는지를 알아보자.
"+" 버튼을 클릭하면 숫자가 증가하는
counter App을 만든다는 가정이다.
Redux React-Redux를 사용했을 경우./* App.js */
import React from “react”;
import { createStore } from “redux”;
import { Provider, useSelector, useDispatch } from “react-redux”;
function reducer(state, action) {
if(action.type === ‘up’) {
return { …state, value: state.value + action.step }
}
return state;
}
const initialState = { value: 0 }
const store = createStore(reducer, initialState);
function Counter () {
const dispatch = useDispatch();
const count = useSelector( state => state.value );
return (
<div>
<button onClick={()=> {
dispatch({ type: ‘up’, step: 2 })
}}> + </button> 0
</div>
)
}
export default function App(){
return (
<Provider store={store}>
<div>
<Counter />
</div>
</Provider>
)
}
Redux toolkitconfigureStore createSlice createAsyncThunk
Redux toolkit이 셋팅된 개발환경이 만들어진다.npx create-react-app 프로젝트명 --template redux
# Vite with our Redux+TS template
# (using the `degit` tool to clone and extract the template)
npx degit reduxjs/redux-templates/packages/vite-template-redux my-app
# Next.js using the `with-redux` template
npx create-next-app --example with-redux my-app
redux-toolkit 추가할 경우npm install @reduxjs/toolkit
yarn add @reduxjs/toolkit
store
Redux를 사용한 경우store안에 모든 store를 넣어 거대한 store를 만든다.Redux-toolkit을 사용한 경우store를 만든다.slice라고 한다.store들을 합쳐서 Redux가 요구하는 큰 store로 Redux-toolkit을 만들어준다.Redux-toolkit을 사용했을 경우"+" 버튼을 클릭하면 숫자가 증가하는
counter App을 만든다는 가정이다.
/* App.js */
import React from “react”;
import { createStore } from “redux”;
import { Provider, useSelector, useDispatch } from “react-redux”;
import { createSlice, configureStore } from “@reduxjs/toolkit”;
const counterSlice = createSlice({
name: ‘counter’,
initialState: { value: 0 },
reducers: {
up: (state, action)=> {
// state.value = state.value + action.step;
state.value = state.value + action.payload;
}
});
const store = configureStore({
reducer: {
counter: counterSlice.reducer // counter에 대한 reducer
}
});
function Counter () {
const dispatch = useDispatch();
const count = useSelector( state => state.counter.value );
return (
<div>
<button onClick={()=> {
// dispatch({ type: ‘counter/up’, step: 2 })
dispatch(counterSlice.actions.up(2))
}}> + </button> 0
</div>
)
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter />
</div>
</Provider>
)
}
slice : [ createSlice ]
slice를 import한다.slice를 만든다. ( createSlice({}) )slice는 counterSlice라고 변수명을 지어줬다.const counterSlice = createSlice({})type별로 함수를 정해준다.Redux reducer는 action.type에 따라 switch 또는 if문으로 해줬지만, Redux-toolkit의 reducer는 type만 적어준다.up: (state, action) => { // .. 함수 실행 } Redux reducer의 내부함수에선 불변성을 지키기 위해 복제를 해서 …기존값을 가져왔지만, Redux-toolkit의 내부함수는 바꿔주고 싶은 값을 간결하게 바꿔줄 수 있다.up Type일 때 처리해야되는 reducer를 만들었다.slice는 하나의 작은 store가 된다.slice들을 여러개 만들어 파일을 만들어 관리하면된다.store : [ configureStore({}) ]
slice들을 모아 store를 만들 때 configureStore를 사용한다.reducer이다. ( 복수형 ❌ )slice들의 reducer가 들어간다.counterSlice의 reducers의 type(up, down, set 등..)들을 하나로 합쳐 하나의 reducer를 자동으로 만들어주는 것이다.store이다.const store = configureStore({})<Provider></Provider> : store를 전달 해주기 위한 태그
useSelector : 전달받은 store에서 정보들을 사용하기 위한 hook
state를 console.log()로 출력했을 시,
counter는 store의 reducer의 이름이다.state => state.value 👉🏻 state => state.counter.value“0”이 표시되는 것을 확인할 수 있다.dispatch()
type은 slice에 해당하는 name을 적고, “/“한 후? 원하는 reducers의 를 적어준다.{ type: slice의 name/원하는 reducers, step: 2 ( 2씩 증가 ) }“step”이라는 명칭을 사용하지 않는 방법이 있다.reducers함수들을 참고해서 자동으로 action을 만들어내는 actionCreate를 만들어준다.dispatch(counterSlice.actions.up(2)) ( actions 복수형⭐️ )Slice에 “up”의 action이 어떻게 찍힐 까 ?
actions를 하고 .up(2)을 하게 되면 payload라는 이름의 약속된 값이 생긴다.Slice의 up함수를 그럼 수정해줘야된다.state.value = state.value + action.payload;App
import react from “react”;
import { Provider, useSelector, useDispatch } from ‘react-redux’;
import store from ‘./store’;
import { up } from ‘./slice/counterSlice’;
function Counte() {
const dispatch = useDispatch();
const count = useSelector(state => {
return state.counter.value
});
return (
<div>
<button onClick={() => {
dispatch(up(2))
}}>+</button> { count }
</div>
);
}
export default function App() {
return (
<Provider store={store}>
<div>
<Counter />
</div>
</Provider>
);
};
Store
/* store.js */
import { configureStore } from ‘@reduxjs/toolkit’;
import counterSlice from ‘./counterSlice’;
const store = configureStore({
reducer: {
counter: couterSlice.reducer
}
});
export default store;
Slice
/* slice/counterSlice.js */
import { createSlice } from ‘@reduxjs/toolkit’;
const counterSlice = createSlice({
name: ‘counter’,
initialState: { value: 0 },
reducers : {
up: (state, action) => {
state.value = state.value + action.payload;
}
}
});
export default counterSlice;
// 간결하게 사용하기 위해서 구조분해할당으로 내보낸다.
export const { up } = counterSlice.actions;