기존 useState 장단점
장점
- 기존에 useState로 상태관리를 했다.
- 추가 라이브러리 없이 React만을 이용해 사용가능
- 간단하고 직관적이며 독립적
단점
- 복잡해지고 사이즈가 커지면 상태 관리가 어려움
- 상태 공유가 어려워서 상태를 여러 컴포넌트에서 공유하려면 context API를 사용해야함
Redux의 장단점
장점
- 중앙에서 관리 가능
- 확장성이 좋아 큰 애플리케이션에서 상태를 효율적으로 관리
- Redux 미들웨어를 사용하여 로깅, 비동기 요청 등을 쉽게 처리할 수 있음
단점
결론
- 작은 애플리케이션은 useState와 useReducer가 충분
- 중간 ~ 큰 애플리케이션은 여러 컴포넌트 간 상태 공유가 많고 상태가 복잡하다면 Redux를 사용
Redux 흐름
- 스토어(Store) 생성 : 중앙 상태 저장소를 생성
createStore
또는 configureStore
함수를 사용하여 생성
- 리듀서(Reducer) 업데이트 - (slice.js)
- 액션을 처리하고 상태를 업데이트하는 함수. 리듀서는 현재 상태와 액션 객체를 입력으로 받아 새로운 상태를 반환
- 컴포넌트에서 상태 사용
- useSelector는 useState의 변수,
- useDispatch는 useState의 setter 같은 개념.
useSelector
와 useDispatch
를 사용하여 컴포넌트에서 상태를 사용하고 변경
실습
store/index.js
import { configureStore } from "@reduxjs/toolkit";
import counterReducer from "./counterSlice";
import authReducer from "./authSlice";
const store = configureStore({
reducer: {
counter: counterReducer,
auth: authReducer,
},
});
export default store;
index.js
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import store from "./redux-cart/store/index";
import { Provider } from "react-redux";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<Provider store={store}>
<App />
</Provider>
);
counterSlice.js
- 액션을 처리하고 상태를 업데이트. 리듀서는 현재 상태와 액션 객체를 입력으로 받아 새로운 상태를 반환
import { createSlice } from "@reduxjs/toolkit";
const initialCountState = {
counter: 0,
showCounter: true,
};
const counterSlice = createSlice({
name: 'counter',
initialState: initialCountState,
reducers: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
},
multiply(state, action) {
state.counter *= action.payload;
},
toggle(state) {
state.showCounter = !state.showCounter;
},
}
});
export const counterActions = counterSlice.actions;
export default counterSlice.reducer;
ReduxCounter.js
- useSelector 훅을 사용하여 Redux 스토어의 상태를 가져오거나 useDispatch 훅을 사용하여 상태값 변경
- 액션은 꼭 dispatch로 묶어서 전송
import React from 'react';
import styles from './ReduxCounter.module.css';
import { useDispatch, useSelector } from 'react-redux';
import { counterActions } from '../store/counterSlice';
const ReduxCounter = () => {
const counter = useSelector(state => state.counter.counter);
const show = useSelector(state => state.counter.showCounter);
const dispatch = useDispatch();
const { increment, decrement, multiply, toggle } = counterActions;
const increaseHandler = e => {
dispatch(increment());
};
const decreaseHandler = e => {
dispatch(decrement());
};
const multiplyHandler = e => {
dispatch(multiply(2));
};
const toggleHandler = e => {
dispatch(toggle());
};
return (
<main className={styles.counter}>
<h1>Redux Counter</h1>
{show && <div className={styles.value}>{counter}</div>}
<div>
<button onClick={increaseHandler}>Increment</button>
<button onClick={decreaseHandler}>Decrement</button>
<button onClick={multiplyHandler}>IncrementDouble</button>
</div>
<button onClick={toggleHandler}>Toggle Counter</button>
</main>
);
};
export default ReduxCounter;
- 여러 리듀서를 제공할 수 있는 store를 만들고
- 필요한 slice를 만들어 초기값설정, reducers는 현재 상태와 액션 객체를 입력으로 받아 새로운 상태를 반환하고 export로 내보냄
- 상태 관리가 필요한 컴포넌트에서 useSelector, useDispatch를 통해 사용