
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
});