Redux는 자바스크립트 앱을 위한 예측 가능한 상태 컨테이너입니다. (Redux Docs)
📍 단방향 데이터 바인딩을 하는 Flux 패턴 의 자바스크립트 구현체라고 생각하자
redux는 기본적으로 하나의 Store 멀티 Reducer의 형태를 갖는다.
즉, store는 하나 그 하나에 여려개의 Reducer가 있다.
리덕스를 사용하면 컴포넌트의 상태 업데이트 관련 로직을 다른 파일로 분리시켜서 효율적으로 관리할 수 있다.
1) View
에서 유저가 일으키는 행동에 맞게 Action
객체가 생성되고,
2) Action은 Dispatcher
를 통해 Reducer
로 전달되고,
3) Action의 type에 따라 Reducer 내에 미리 정해져 있던 로직이 Store
를 변경하고,
4) 변경된 Store의 내용이 View
로 반영되는 패턴이라고 요약할 수 있음.
상태에 변화가 필요하다면 액션을 일으켜야한다.
Action
은 중앙 저장소에 저장된 state
에 “무슨” 동작을 할 것이지 적어놓는 객체입니다.
Action
에는 type
이 필수로 필요합니다.
//action types
const ADD_CART = 'ADD_CART'
```
Action Creator
는 이러한 Action 객체를 정해진 틀에 맞게 리턴하는 단순한 함수.```jsx
export const addCart = (item) => { // 액션 "생성 함수"
return {
type: "ADD_CART", // 액션 "객체"
payload: item,
};
};
```
store.dispatch
함수의 인자로 담겨 reducer
에 어떻게 store를 변경시킬 것인지
에 대한 정보를 제공 하는 역할type
프로퍼티를 제외하면, 사용자의 필요에 따라 추가 가능const ADD_TODO = {
type: "ADD_CART",
payload: { content: "출근하기", priority: 1 }
}
store.dispatch()
형태로 제공됨. //addTodo를 담고 reducer로 향하는 dispatch열차
dispatch(addTodo(text))
위와 같이 작성하게 되면 매번 dispatch안에 action creator를 호출해서 사용해야하기 때문에 아래와 같이 함수를 만들어서도 사용함.
const boundAddTodo = text => dispatch(addTodo(text))
boundAddTodo(text)
dispatch
로 넘어온 action
의 type
을 확인해서 그에 맞는 동작을 하는 곳.
동작을 하기 때문에 function
으로 작성이 됩니다.
Reducer는 (previousState, action) => newState
의 형태를 가지고, 순수함수이며 예측 가능해야 합니다.
Reducer는 업데이트 되기 이전의 Store를 기반으로 새로 받은 Action에 미리 준비된 로직을 처리해 새로운 Store를 리턴하는 함수
입니다. 즉, Reducer는 감지된 Action 타입에 따라 이벤트를 처리하는 이벤트 리스너로도 생각할 수 있습니다.
// Array.prototye.reduce()
const cart = [
{ id: 1, name: "청바지", price: 10000, quantity: 2 },
{ id: 2, name: "반바지", price: 10000, quantity: 1 },
{ id: 3, name: "반팔", price: 10000, quantity: 2 },
]
const totalPrice = cart.reduce((acc, cur) => {
return acc + cur.price * cur.quantity
}, 0)
```
redux의 Reducer 역시 Store와 Action을 받아 새로운 Store로 값을 합쳐 내보냅니다.
``` jsx
const INITIAL_STATE = [];
// redux/cart.js
export default function cartReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case "ADD_ITEM":
return [...state, action.payload]; // 이전 상태에 새로운 item을 추가
case "DELETE_ITEM":
return state.filter((product) => product.id !== payload.id);
default:
return state; // 해당 사항 없으면 이전 상태를 그대로 리턴
}
}
// redux/index.js
import { combineReducers } from "redux";
import cartReducer from "./cartReducer";
export default combineReducers({ cartReducer });
Root Reducer
: 실제로 createStore
의 첫 번째 인자로 전달되는 함수입니다. 유일하게 (state, action) => newState
형태의 로직을 가져야 합니다.Slice Reducer
: 상태 트리의 일부분만을 업데이트하는 리듀서입니다. 여러 Slice Reducer들이 결합(combineReducers
)되어 Root Reducer를 구성하게 됩니다.:: 주의 사항
Promise(fetch)
, Math.random()
, new Date()
스토어에는 상태가 들어있다. 하나의 프로젝트는 하나의 스토어만 가질 수 있다.
store는 모든 컴포넌트에서 사용할 수 있는 Global State를 저장해놓는 저장소 입니다.
하지만 이 state는 엄격하게 관리해야 하기 때문에 dispatch라는 함수를 통해서만 state에 접근이 가능하다.
import { createStore } from 'redux'
import todoApp from './reducers'
const store = createStore(todoApp)