Redux
๋ UI
์์ Action
์ด ์๊ธฐ๊ณ ์ด Action
์ dispatch
๊ฐ ๋ฐ์ ๋์ ธ์ฃผ๊ณ Reducer
๊ฐ ๋ฐ์ ์์
์ง์๋ฅผ return
์ ํ๋ฉด state
๊ฐ ๋ฐ์์ฃผ๋ ์๋ฆฌ์ด๋ค.
์ด Redux
์๊ฒ ๋จ์ ์ด ์๋ค. ๋จ์ ์ด ๋ฌด์์ด๋๋ฉด ๋น๋๊ธฐ์ ์ฒ๋ฆฌ๋ฅผ ํ์ง ๋ชปํ๋ ๊ฒ์ด๋ค.
Redux
๋ ๋๊ธฐ์ ์ฒ๋ฆฌ๋ฅผ ํ๊ธฐ ๋๋ฌธ์ ๋ง์ฝ A๋ฅผ ๋ฐ๊ฟ๋ฌ๋ผ๊ณ ์์ฒญํ๋ฉด ์ฝ๋๊ฐ ์์ฐจ์ ์ผ๋ก ์คํ๋๋ฉฐ ๋ฐ๋ก ๋ฐ๊ฟ์ค๋ค. ๊ทธ๋์ API ์์ฒญ๊ฐ์ ๋น๋๊ธฐ์ ์์
์ด ๋ถ๊ฐ๋ฅ ํ๋ค๋ ๋จ์ ์ด ์๋ค.
์ด ๋จ์ ์ ์ฒ๋ฆฌ ํ๊ธฐ ์ํด ๋ง๋ค์ด์ง ๊ฒ์ด Redux middleware
์ด๋ค.
Redux middleware
๋ Redux
์๋ฆฌ์ ๊ฐ์ง๋ง ์๋๋ผ๋ฉด dispatch
๊ฐ ๋์ ธ์ฃผ๋ Action
์ ๋ฐ๋ก Reducer
๊ฐ ๋ฐ์์ง๋ง Redux middleware
๊ฐ ์ค๊ฐ์ ๊ฑฐ์ณ๊ฐ๋ค.
Redux middleware
์์ ํจ์๋ฅผ ๋ง๋ค ์ ์์ด ์ฌ๊ธฐ์ ๋น๋๊ธฐ์ ์ฒ๋ฆฌ๋ฅผ ํ๊ฒ ๋๊ณ ๋น๋๊ธฐ์ฒ๋ฆฌ๊ฐ ๋๋๋ฉด ๋ค์ dispatch
๋ก ๋์ ธ์ค return
ํด state
๊ฐ ๋ฐ์์ฃผ๋ ์๋ฆฌ์ด๋ค.
middle ware
๋ ์ด๋ค ์ปจ์
์ ์ด๋ฆ์ด๊ณ , ์ค๊ฐ์ ๊ฐ๋ก์ฑ๋ค๋ ์๋ฏธ์ด๋ค.
Redux middleware
์๋ ๋ ๊ฐ์ง ์ข
๋ฅ๊ฐ ์๋ค. redux-saga, redux-thunk
๊ฐ ์๋ค.
์ฌ๊ธฐ์ ์ ์ฉํ ๊ฒ์ redux-thunk
๋ฅผ ์ ์ฉํด ๋ณผ ๊ฒ์ด๋ค.
redux-thunk์ ์ค๋ช ์ด ๋์ด ์๋ค.
๋จผ์ ์์
ํ๊ณ ์ ํ๋ ํ๋ก์ ํธ์ Redux
์ React-Redux
๋ฅผ ์ค์นํ๋ค.
npm install redux react-redux
yarn add redux react-redux
๊ทธ ํ redux-thunk
๋ฅผ ์ค์นํ๋ค.
npm install redux-thunk
yarn add redux-thunk
์ดํ ์ ์ฉ ๋ฐฉ๋ฒ์ redux ์ ์ฉ๋ฐฉ๋ฒ์ ์ฐธ๊ณ ํ๋ฉด ๋๋ค.
์ ๋ฐฉ๋ฒ์ ์ ์ฉํ๋ค๋ฉด store.js
ํ์ผ์ ์ถ๊ฐ๋ฅผ ํด์ค์ผ ํ๋๋ค.
import {createStore, applyMiddleware} from "redux";
import thunk from 'redux-thunk' //์ถ๊ฐ
import rootReducer from "./reducers";
let store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
์ด๋ ๊ฒ ๋ฏธ๋ค์จ์ด๋ฅผ ์ฌ์ฉ์ค๋น๊ฐ ์๋ฃ๋ ๊ฒ ์ด๋ค.
API ์์ฒญ์ ์๋ฅผ ๋ค์ด ์ ์ฉํ ๊ฒ ์ด๋ค.
redux ํด๋ ์์ actions ๋ผ๋ ํด๋๋ฅผ ๋ง๋ค์ด ์ํ๋ ํ์ผ๋ช ์ผ๋ก ํ์ผ์ ๋ง๋ค์ด ์ค๋ค.
๋ง๋ ํ์ผ์ ํจ์๋ฅผ ๋ง๋ค์ด ์ค๋ค.
๊ธฐ์กด์ ์๋ API ์์ฒญ ํจ์๋ฅผ ๋ฏธ๋ค์จ์ด๋ก ๋ณ๊ฒฝ ํด๋ณด์
const [productList, setProductList] = useState('');
const getProducts = async () => {
let searchQuery = query.get('q') || "";
dlet url = `https://my-json-server.typicode.com/jjunseokk/hnm-site/products?q=${searchQuery}`;
let response = await fetch(url);
let data = await response.json();
setProductList(data);
};
const productList = useSelector((state)=>state.product.productList); //reducer๋ฅผ ๊ฐ์ ธ์จ ๊ฒ.
const dispatch =useDispatch();
const getProducts = () => {
let searchQuery = query.get('q') || "";
dispatch(productAction.getProducts(searchQuery));
};
function getProducts(searchQuery) {
return async (dispatch, getState) => {
let url = `https://my-json-server.typicode.com/jjunseokk/hnm-site/products?q=${searchQuery}`;
let response = await fetch(url);
let data = await response.json();
dispatch({type : "GET_PRODUCT_SUCCESS", payload : {data}});
};
}
๊ทธ๋ฆฌ๊ณ ์ด์ dispatch
๊ฐ ๋ณด๋ด๋ `reducer๋ฅผ ๋ฐ๋ผ์ ๋ง๋ค์ด ์ฃผ๋ฉด ๋๋ค.
let initialState = {
productList: [],
selectedItem: null,
}
function productReducer(state = initialState, action) {
let { type, payload } = action;
switch (type) {
case "GET_PRODUCT_SUCCESS":
return { ...state, productList: payload.data };
default:
return { ...state };
}
}
export default productReducer;
let initialState = {
productList: [],
selectedItem: null,
}
function productReducer(state = initialState, action) {
let { type, payload } = action;
switch (type) {
case "GET_PRODUCT_SUCCESS":
return { ...state, productList: payload.data };
case "GET_SINGLE_PRODUCT_SUCCESS":
return { ...state, selectedItem: payload.data };
default:
return { ...state };
}
}
export default productReducer;
let initialState = {
id : '',
password : '',
authenticate : false
}
function authenticateReducer (state=initialState, action){
let {type, payload} =action;
switch(type){
case "LOGIN_SUCCESS" :
return {...state, id : payload.id, password : payload.password, authenticate : true};
default :
return {...state};
};
}
export default authenticateReducer;
์ ๋ reducer
๋ฅผ ํ๋ฒ์ ์ ์ฉํ ๋ CombineReducer๋ฅผ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ๊ฐ๋ฅผ ํฉ์น ์ ์๋ค.
์๋์ฒ๋ผ index.js
ํ์ผ์ ๋ง๋ค์ด ์๋์ ๊ฐ์ด ์์ฑํ๋ฉด ๋๋ค.
import { combineReducers } from "redux";
import authenticateReducer from "./authenticateReducer";
import productReducer from "./productReducer";
export default combineReducers({
auth : authenticateReducer,
product : productReducer
});