✅ Redux의 동작 원리
✅ Redux in javascript
✅ Redux in React
🚀 Redux의 동작 원리
- redux의 핵심은 store라는 central Data를 관리하는 기능으로 모든 state를 관리할 수 있도록 돕는 라이브러리이다.
- store를 생성하고, 해당 store를 subscription하는 컴포넌트에 전달을 하고, 컴포넌트는 dispatch를 통해 action이라는 것을 통해 값을 전달하고, 리듀서 함수에서 해당 값을 전달받아 값을 변경해준다.
- 그리고 이를 다시 store의 state로 값을 변경하는 것이 redux의 동작원리이다.
const redux = require('redux');
const counterReducer = (state= {counter : 0}, action) => {
if(action.type === 'increment') {
return {counter: state.counter + 1}
}
if (action.type === 'decrement') {
return {
counter : state.counter -1
}
}
return state;
}
const store = redux.createStore(counterReducer)
const counterSubscriber = () => {
const latestState = store.getState()
console.log(latestState);
};
store.subscribe(counterSubscriber)
store.dispatch({ type:'increment'})
store.dispatch({ type:'decrement'})
🚀 Redux in javascript
- redux는 react만을 위해서 존재하지 않으며, 바닐라 자바스크립트 외의 vue, angular 등에서도 활용이 가능하다.
- javascript에서 redux 활용은 크게 4가지 단계로 이루어진다.
- store 생성
- store는 기본적으로 두 가지 인자를 전달받는다, state와 action. 그리고 이를 특정 값으로 return하는 함수를 생성한다. 이 때 state는 초기값을 가져야하고, return하는 함수의 형태는 보통 객체 데이터로 만든다.
- store 전달
- store를 만들었으면, redux.createStore로 만든 reducer를 전달해주고,해당 store를 읽기 위해서 subscribe 함수를 만든다. 이를 store.subscribe()로 해당 함수를 전달해준다.
- dispatch로 action 전달
- action을 생성하는데, 어떤 형태로든 전달이 가능하다. 그런데 type으로 객체값을 넘긴다고 가정하면 store.dispatch({type:'increment'})로 값을 전달해줄 수 있다.
우리는 Redux를 활용해 React에서 간단하게 버튼 클릭시 값을 더해주는 카운터를 만들 것이다.
import { createStore } from 'redux'
const initialState = {counter:0, show:true}
const conunterReducer = (state = initialState, action) => {
if (action.type === 'increment') {
return {
counter : state.counter + 1,
show : state.show
}
}
if (action.type === 'decrement') {
return {
counter : state.counter - 1,
show : state.show}
}
if (action.type === 'increase') {
return {
counter : state.counter + action.amount,
show : state.show
}
}
if (action.type === 'toggle') {
return {
show : !state.show,
counter : state.counter
}
}
return state
}
const store = createStore(conunterReducer);
export default store;
🚀 store 구조
- 위에서 이야기했던 store 구조의 3단계 뭐였지? 1. store 만들기. react에서는 store 파일에서는 store만 만들어 줄 것이다. 왜냐? 우리는 아주아주 유용한 훅이 있기 때문이다.
- store는 마찬가지로 두 가지의 인자를 받아서 특정 조건일 때 객체를 리턴해서 state를 변경해줄 것이다.
import { useSelector, useDispatch }from 'react-redux'
import classes from './Counter.module.css';
const Counter = () => {
const dispatch = useDispatch()
const counter = useSelector(state => state.counter)
const show = useSelector(state => state.show)
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}>Increase by 5</button>
<button onClick={decrementHandler}>Decrement</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
export default Counter;
🚀 counter.js 구조
- 기존 자바스크립트에서는 아래와 같이 생성한 store의 state를 따로 할당해주고 이를 subscribe를 해줘야만 store값을 불러올 수 있었다. 뿐만아니라 store의 dispatch를 하기 위해서도 store의 내장객체인 dispatch를 불러왔어야만 했다.
const counterSubscriber = () => { const latestState = store.getState() console.log(latestState); }; store.subscribe(counterSubscriber) store.dispatch({ type:'increment'}) store.dispatch({ type:'decrement'})
- 그러나 리액트에서는 아까 말했듯이 어마무시한 use훅을 사용한다고 했다. 그 두 가지가 바로 useDispatch와 useSelector이다. useDispatch()를 react-redux에서 호출만 해주면 바로 사용을 할 수 있고, useSelector 또한 state내의 값들을 변화할 수 있게 자동으로 할당을 해준다.
const dispatch = useDispatch() const counter = useSelector(state => state.counter) const show = useSelector(state => state.show)
- 따라서 우리는 위와 같이 변수에 할당만 해준다면 해당 state값을 업데이트 할 수 있게 된다.