๐ ํ์ผ ๊ตฌ์กฐ
๐ actions/index.js
// action types
export const ADD_TO_CART = "ADD_TO_CART";
export const REMOVE_FROM_CART = "REMOVE_FROM_CART";
// actions creator functions
export const addToCart = (itemId) => {
return {
type: ADD_TO_CART,
payload: {
quantity: 1,
itemId
}
}
}
export const removeFromCart = (itemId) => {
return {
type: REMOVE_FROM_CART,
payload: {
itemId
}
}
}
reducer ํจ์์ ์ธ์๋ก ์ ํด์ฃผ๊ณ ์ถ์ action๋ค์ด ๊ฐ๋๊ฐ๋ ๋ค์ด์๋ค.
Redux๋ฅผ ์ฐ๊ธฐ ์ , props๋ก ๋ฐ์ดํฐ๋ฅผ ๋ด๋ ค๋ณด๋ด๊ณ ์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ํ ๋ณ๊ฒฝ ํ ๋์ด์ฌ๋ ค ์ ๋ฐ์ดํธํ๋ ๊ทธ ์์ ์ !
์ํ๋ฅผ ๋ณ๊ฒฝ์์ผ์ฃผ๋ ํจ์์ "์ธ์"๋ค์ ์์๊ฒ ์ ๋ฆฌํด๋์ ๊ฑฐ๋ผ๊ณ ๋ณด๋ฉด ๋๊ฒ ๋ค.
์ปดํฌ๋ํธ ๋ด๋ถ์์ ์ํ๋ฅผ ์ ๋ฐ์ดํธ ์์ผ์ค ๋๋
๊ธฐ์กด์ ๋ฐ์ดํฐ ํ์์ ๋ง์ถ ์ธ์๋ฅผ ์ ๋ฌํด์ผํ๊ธฐ ๋๋ฌธ์ ์ธ์ ์์ฒด๋ ๊ตฌ์กฐ๊ฐ ๋ณต์กํ๋ค. ๊ธฐ์ตํ์ง ?
ex. { name: lee, age: 20, height: 190 } => ์ด ์์ฒด๋ฅผ ์ ๋ฌํด์ ์ํ๋ฅผ ์ ๋ฐ์ดํธ ์์ผ์ฃผ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์๋ค๊ตฌ !!
action์ "๋ฌด์์"๋ง ์ ์ํด์ค๋ค. "์ด๋ป๊ฒ"์ ๋ํ ์ฒ๋ฆฌ ๊ณผ์ ์ ํฌํจํ์ง ์๋ ๊ฒ์ด ํต์ฌ์ด๋ค. (type๊ณผ payload๋ง ๐)
์์ํ JSON ํํ์ ๊ฐ์ฒด์ฌ์ผ์ง๋ง ์ถํ์ History ๊ด๋ฆฌ๊ฐ ํธํ๊ณ , ์ฝ๊ฒ ์ฌ์ฌ์ฉํ ์ ์๋ค.
๐ reducers/index.js
import { combineReducers } from 'redux';
// itemReducer์ notificationReducer ๋ชจ๋ reducer ํจ์๋ค ๐
import itemReducer from './itemReducer';
import notificationReducer from './notificationReducer';
const rootReducer = combineReducers({
itemReducer,
notificationReducer
});
export default rootReducer;
โพ combineReducers
์๋ก ๋ค๋ฅธ Reducing ํจ์๋ค์ ๊ฐ์ผ๋ก ๊ฐ์ง๋ ๊ฐ์ฒด๋ฅผ ๋ฐ์์ => { itemReducer, notificationReducer }
{ itemReducer, notificationReducer } == { itemReducer : itemReducer, notificationReducer : notificationReducer }
createStore์ ์ธ์๋ก ๋๊ธธ ์ ์๋ ํ๋์ Reducing ํจ์๋ก ๋ฐ๊ฟ์ค๋ค. ์ฆ, Function์ ๋ฆฌํดํ๋ค.
โป combineReducers๋ ๋ฆฌ๋์ ๊ณ์ธต์ ์ต์์๋ฟ๋ง ์๋๋ผ ์ด๋ ๋จ๊ณ์์๋ ํธ์ถํ ์ ์๋ค !
โป code ๋ณต์กํด์ง๋ฉด ๋ง์๊ป ๋ถ๋ฆฌํ๊ณ ๋ง์๊ป ํฉ์น์๊ธธ ^!^
๐ reducers/itemReducer.js
import { REMOVE_FROM_CART, ADD_TO_CART } from "../actions/index";
import { initialState } from "./initialState";
const itemReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TO_CART:
let copyState1 = Object.assign({}, state);
copyState1.cartItems = state.cartItems.concat(action.payload);
return copyState1;
case REMOVE_FROM_CART:
let copyState2 = Object.assign({}, state);
copyState2.cartItems = state.cartItems.filter((el) => el.itemId !== action.payload.itemId);
return copyState2;
default:
return state;
}
}
export default itemReducer;
reducer๋ฅผ ์์ฑํ ๋ ์ง์ผ์ผํ๋ ๊ท์น์ด ์์ด์ ์ ๊น ์ง๊ณ ๋์ด๊ฐ๋ คํ๋ค.
โ ๋ชจ๋ ์ํ๊ฐ undefined์ผ๋๋ ์ฒซ๋ฒ์งธ ์ธ์๋ก ์ฃผ์ด์ง state๋ฅผ ๋ฐํํด์ผํ๋ค.
โ reducer๋ undefined๋ฅผ ๋ฐํํด์๋ ์๋๋ค. => undefined ๋ฐํ๋๋ฉด ์๋ฌ๋๋ค.
โ state๊ฐ undefined๋ก ์ฃผ์ด์ก์ ๋๋ undefined ๋ฐํ X ํด๋น reducer์ ์ด๊ธฐ ์ํ๋ฅผ ๋ฐํํด์ผํ๋ค.
=> Redux.createStore( combineReducers(...), initialState )๋ฅผ ์ฌ์ฉํด ์ด๊ธฐ ์ํ๋ฅผ ๋ช ์ํ๋๋ผ๋
reducer์ undefined๋ฅผ ์ ๋ฌํด์ ์ง์ ํ์ธํ๋ค๊ณ ... ๋ฆฌ๋์คใทใทใท
๐ reducers/initialState.js
export const initialState = {
"items" : [
{
"id": 1,
"name": "2021 ๋ฌ๋ ฅ",
"price": 10000
},
{
"id": 2,
"name": "์๊ฐ์๊ฐ๋ฃฌ ์์ฆ",
"price": 35000
}
],
"cartItems" : [
{
"itemId": 1,
"quantity": 3
},
{
"itemId": 2,
"quantity": 10
}
]
}
์ํ์ ์ด๊ธฐ ์ ๋ณด๊ฐ reducer ํจ์๋ค๊ณผ ํจ๊ป ์๋๋ผ. ๋ฐ์ดํฐ์ ์์น๊ฐ ์ ๊ธฐํด์ ใ ใ ๊ฐ์ ธ์๋ดค๋ค.
๊ฐ๋ ์ ์ผ๋ก๋ณด๋ฉด store์ ์ด๊ธฐ์ ๋ณด๊ฐ ๋ค์ด์์๊ฒ๊ฐ์๋ค.
์ ์ ์ด๊ธฐ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๋ ๊ฑด reducer ํจ์๋ค์ด๋๊น !! ๊ธฐ์ตํ์ ๐
์์ ๋งํ๋ฏ์ด createStore( )ํจ์๊ฐ undefined๋ฅผ ๋ณด๋ด์ reducer๊ฐ ์ด๊ธฐ State๋ฅผ ์์ ํ๊ฒ ๋ฐํํ๋์ง ์ํ๋์ง ํ์ธ๋ ํ๋ค๊ณ ํ์ผ๋๊น, store์ ์ด๊ธฐ ์ํ๋ฅผ ์ ๋ฌํ๋ ๊ฑด ํฐ ์๋ฏธ๊ฐ ์๋ ๊ฒ ๊ฐ๋ค๊ณ ์ ์ถํด๋ณธ๋ค. reducer์ ์ด๊ธฐ๋ฐ์ดํฐ๋ ์ง๊ถ์ด๋ผ๊ณ ์๊ฐํด์ผ๊ฒ ๋ค
reducer๋ ๋ฐ์ดํฐ์ ์๋ณธ์ ์ฒ๋ฆฌํ๋ ๊ณผ์ ์ ํ ๋์ ๋ณผ ์ ์๋ ์ค์ํ ์์น์ด๋ค.
๐ store/store.js
import { compose, createStore, applyMiddleware } from "redux";
import rootReducer from '../reducers/index';
import thunk from "redux-thunk";
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) : compose;
const store = createStore(rootReducer, composeEnhancers(applyMiddleware(thunk)));
export default store;
๐ window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
ํฌ๋กฌ ํ์ฅ ํ๋ก๊ทธ๋จ์ ์์ฑ๋์ด ์๋ ์๋ฐ์คํฌ๋ฆฝํธ ํจ์ (๋ฆฌ๋์ค ๊ฐ๋ฐ์ ๋๊ตฌ)
โพ compose(...functions)
ํจ์๋ฅผ ์ค๋ฅธ์ชฝ์์ ์ผ์ชฝ์ผ๋ก ์กฐํฉํ๋ ์ญํ .
โพ createStore(reducer, [preloadedState])
Redux Store(์ํ ํธ๋ฆฌ ์ ์ฒด๊ฐ ๋ณด๊ด๋์ด ์๋ ๊ณณ)๋ฅผ ์์ฑ. 1๊ฐ์ ์ฑ์ 1๊ฐ์ ์คํ ์ด โญ
โ reducer
(Function) Reducing function์ผ๋ก, ๋ณํ๋ ์ํ ํธ๋ฆฌ๋ฅผ ๋ฐํํ๋ค.
โ [ preloadedState ]
์ด๊ธฐ์ํ๋ฅผ ์ ๋ฌํ ์ ์๋ค.
์ ๋๋ฒ์ ์ฑ์ ์๋ฒ๋ ์ด์ ์ ์ง๋ ฌํ๋ ์ฌ์ฉ์ ์ธ์ ์์ "์ํ๋ฅผ ์ฑ์ฐ๊ธฐ ์ํด" ์ ํ์ ์ผ๋ก ์ง์ ํ ์ ์๋ค.
โ [ enhancer ]
Store Enhancer๋ฅผ ์ ๋ฌํ ์ ์๋ค. (applyMiddleware( ) ๋ฐ์ ์์ ^_^)
middleware, third-party feature (time travel , persistance) ๊ธฐ๋ฅ์ Store์ ์ถ๊ฐํ๊ธฐ ์ํด ์ง์ ํ ์ ์๋ค.
โพ applyMiddleware(...middlewares ๋ฏธ๋ค์จ์ด๋ค)
Redux์ Middleware(์์์ ํจ์)๋ฅผ ๋ํด ๊ธฐ๋ฅ์ ํ์ฅํ๋ ๊ฒ์ ๋์์ค๋ค.
์ถ๊ฐ๋ ์ฌ๋ฌ ๊ฐ์ ๋ฏธ๋ค์จ์ด๋ (๋ฏธ๋ค์จ์ด ์ฒด์ธ ๋ด์์) ์๋ก์ ๋์์ ์ํฅ์ ๋ผ์น์ง ์๋๋ค.
๊ฐ๊ฐ์ ๋ฏธ๋ค์จ์ด๋ Store์ dispatch์ getState ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์, ํจ์๋ก ๋ฐํํ๋ค.
์ด ํจ์๋ ๋ฏธ๋ค์จ์ด์ ๋์คํจ์น ํจ์์์ next๋ก ์ฃผ์ด์ง๊ณ , next๋ action์ ์ธ์๋ก ๋ฐ์ ํธ์ถ๋๋ค.
์ฒด์ธ์ ๋ง์ง๋ง ๋ฏธ๋ค์จ์ด๋ next์ ์ธ์๋ก ์๋์ dispatch๋ฅผ ๋ฐ์ ์ฒด์ธ์ ๋ง๋ฌด๋ฆฌํ๋ค.
์ต์ข ์ ์ผ๋ก ๋ฐํ๋๋ ๊ฐ์ Store Enhancer๋ก, ์ฃผ์ด์ง ๋ฏธ๋ค์จ์ด๋ฅผ ์ ์ฉํ๋ ํจ์์ด๋ค.
๊ฐ์ฅ ๊ธฐ๋ณธ์ ํํ : ({ getState, dispatch }) => next => action
// ์ฝ๋ ์์
import { createStore, applyMiddleware } from 'redux';
import memo from './reducers';
function logger({ getState }) {
return (next) => (action) => {
console.log('will dispatch', action)
// Call the next dispatch (in the middleware chain)
let returnValue = next(action);
console.log('state after dispatch', getState())
return returnValue
}
}
let store = createStore(
memo,
[ 'Use Redux' ],
applyMiddleware(logger)
);
store.dispatch({
type: 'ADD_MEMO',
text: 'Understand the middleware'
})
// (These lines will be logged by the middleware:)
// will dispatch: { type: 'ADD_MEMO', text: 'Understand the middleware' }
// state after dispatch: [ 'Use Redux', 'Understand the middleware' ]
๐ ์ฌ๊ธฐ์ ์๊ธฐ๋ ์ถ๊ฐ ์ง๋ฌธ
๊ทธ๋ ๋ค๋ฉด, ๋ฏธ๋ค์จ์ด์ ์ข ๋ฅ์๋ ์ด๋ ํ ๊ฒ๋ค์ด ์๋๊ฐ?
๊ทธ๋ฆฌ๊ณ ๋ฏธ๋ค์จ์ด๋ ์ ํ์ด ๋ฌด์์ธ๊ฐ??
'Front-end > Redux' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Redux 3๊ฐ์ง ์์น ์ ๋ฆฌ (0) | 2021.11.04 |
---|---|
React๋ฅผ ์ฐ๋ค๋ณด๋ Redux๊ฐ ๊ถ๊ธํด์ก๋ค (0) | 2021.08.18 |
๋๊ธ