Redux
A state management system for cross-component or app-wide state
- 우리가 상태, 즉 ! 우리의 애플리케이션을 변경하고 화면에 표시하는 데이터를 관리하도록 도와주는 상태 관리 라이브러리
- 우리가 데이터를 다수의 컴포넌트나 심지어 앱 전체에서 관리하도록 도와준다
- 유동적인 상태 관리 라이브러리
Redux 작동 방식
- 중앙 데이터 저장소(store)은 하나뿐이다.
- 컴포넌트는 저장소를 구독하고 변화를 감지한다.
- 변화된 데이터를 가져와서 UI에 보여준다.
- UI상 변화가 생기면 action 을 통해 reducer 순수 함수에 전달.
- 순수 함수로만 state 변경이 가능하다.
Redux 사용하기
- Redux 는 JavaScript(자바스트립트) 상태관리 라이브러리이다.
- React 에서 작업을 하기 위해서는
npm install redux react-redux
설치 해야함
store - index.js
import { createStore } from 'redux';
export const INCREMENT = 'increment';
const initialState = { counter: 0, showCounter: true };
function counterReducer(state = initialState, action) {
if (action.type === INCREMENT) {
return {
counter: state.counter + 1,
showCounter: state.showCounter,
};
}
if (action.type === 'increase') {
return {
counter: state.counter + action.amount,
showCounter: state.showCounter,
};
}
if (action.type === 'decrement') {
return {
counter: state.counter - 1,
showCounter: state.showCounter,
};
}
if (action.type === 'toggle') {
return {
counter: state.counter,
showCounter: !state.showCounter,
};
}
return state;
}
const store = createStore(counterReducer);
export default store;
Counter.js
import { useSelector, useDispatch } from 'react-redux';
import classes from './Counter.module.css';
import { INCREMENT } from '../store/index';
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const show = useSelector((state) => state.showCounter);
const incrementHandler = () => {
dispatch({ type: INCREMENT });
};
const increaseHandler = () => {
dispatch({ type: 'increase', amount: 5 });
};
const decrementHandler = () => {
dispatch({ type: 'decrement' });
};
const toggleCounterHandler = () => {
dispatch({ type: '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}>Increment by 5</button>
<button onClick={decrementHandler}>Decrement</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
export default Counter;
- 항상 새로운 상태 스냅숏을 반환해야 한다, 초기값을 변경하면 안된다
- 애플리케이션 규모가 커질수록 문제가 발생 !
- action type
- 관리하는 데이터의 양
- 가지고 있는 데이터와 상태가 많을수록, 상태 객체도 점점 커짐 !!
- 즉, 많은 상태를 복사해야하는 경우가 생긴다.
- 또한 그 모든 상태 속성을 유지하려면, 조건문 또는 함수가 늘어날 수 가 있다.
- 꼭 지켜줘야 하는 상태의 변경 불가성 (초기값!)
- 특히 중첩된 객체 및 배열에 있어서 복잡한 데이터를 가지고 있을 때, 중첩된 데이터를 실수로 바꾸면서 망치기 쉽다
- Redux toolkit : 리덕스 만든 사람이 만들었어요.
npm install @reduxjs/toolkit
설치
- 설치하고 나면
package.json
에서 redux
삭제
- 이미 Redux toolkit에 포함되어 있기때문
store - index.js
import { createSlice, configureStore } from '@reduxjs/toolkit';
const initialState = { counter: 0, showCounter: true };
const counterSlice = createSlice({
name: 'counter',
initialState,
reducers: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
},
increase(state, action) {
state.counter = state.counter + action.payload;
},
toggleCounter(state) {
state.showCounter = !state.showCounter;
},
},
});
const store = configureStore({
reducer: counterSlice.reducer,
});
export const counterActios = counterSlice.actions;
export default store;
counter.js
import { useSelector, useDispatch } from 'react-redux';
import { counterActios } from '../store/index';
import classes from './Counter.module.css';
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const show = useSelector((state) => state.showCounter);
const incrementHandler = () => {
dispatch(counterActios.increment());
};
const increaseHandler = () => {
dispatch(counterActios.increase(5));
};
const decrementHandler = () => {
dispatch(counterActios.decrement());
};
const toggleCounterHandler = () => {
dispatch(counterActios.toggleCounter());
};
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}>Increment by 5</button>
<button onClick={decrementHandler}>Decrement</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
export default Counter;