리덕스를 정리하고자 유튜브에 Codevolution 채널(https://www.youtube.com/channel/UC80PWRj_ZU8Zu0HSMNVwKWw)에서 React Redux Toturial을 학습했다.
벨로퍼트와 함께하는 모던 리액트(https://react.vlpt.us/rhttps://react.vlpt.us/edux/)
const redux = require("redux");
const createStore = redux.createStore;
const store = createStore(reducer)
// type 필드를 필수적으로 가지고 있어야 한다.
{
type: BUY_CAKE,
}
const reducer = (state = initialState, action) => {
switch (action.type) {
case BUY_CAKE:
return { ...state, numOfCakes: state.numOfCakes - 1 };
case BUY_ICECREAM:
return { ...state, numOfIceCreams: state.numOfIceCreams - 1 };
default:
return state;
}
};
redux의 비동기 작업에는 미들웨어가 필요하다.
우선은, redux-logger
로 먼저 미들웨어를 적용해보자.
const reduxLogger = require("redux-logger");
const logger = reduxLogger.createLogger();
const applyMiddleware = redux.applyMiddleware;
const store = createStore(rootReducer, applyMiddleware(logger));
이를 바탕으로 redux-thunk
적용한 코드
const redux = require("redux");
const createStore = redux.createStore;
const applyMiddleware = redux.applyMiddleware;
const thunkMiddleware = require("redux-thunk").default;
const axios = require("axios");
const initialState = {
loading: false,
users: [],
error: "",
};
// action
const FETCH_USER_REQUEST = "FETCH_USER_REQUEST";
const FETCH_USER_SUCCESS = "FETCH_USER_SUCCESS";
const FETCH_USER_FAILURE = "FETCH_USER_FAILURE";
// action creator
const fetchUsersRequest = () => {
return {
type: FETCH_USER_REQUEST,
};
};
const fetchUsersSuccess = (users) => {
return {
type: FETCH_USER_SUCCESS,
payload: users,
};
};
const fetchusersFailure = (error) => {
return {
type: FETCH_USER_FAILURE,
payload: error,
};
};
// reducer
const reducer = (state = initialState, action) => {
switch (action.type) {
case FETCH_USER_REQUEST:
return {
...state,
loading: true,
};
case FETCH_USER_SUCCESS:
return {
loading: false,
users: action.payload,
error: "",
};
case FETCH_USER_FAILURE:
return {
loading: false,
users: [],
error: action.payload,
};
}
};
const fetchUsers = () => {
return function (dispatch) {
dispatch(fetchUsersRequest());
axios
.get("https://jsonplaceholder.typicode.com/users")
.then((res) => {
// res.data
const users = res.data.map((user) => user.id);
dispatch(fetchUsersSuccess(users));
})
.catch((e) => {
// error.message
dispatch(fetchusersFailure(error.message));
});
};
};
// store
const store = createStore(reducer, applyMiddleware(thunkMiddleware));
store.subscribe(() => {
console.log(store.getState());
});
store.dispatch(fetchUsers());
connect
는 HOC입니다. HOC란, Higher-Order Component 를 의미하는데요, 이는 리액트 컴포넌트를 개발하는 하나의 패턴으로써, 컴포넌트의 로직을 재활용 할 때 유용한 패턴입니다.
리액트에 Hook 이 도입된 이후에는 HOC를 만들 이유가 없어졌습니다.
HOC의 용도는 "컴포넌트를 특정 함수로 감싸서 특정 값 또는 함수를 props로 받아와서 사용 할 수 있게 해주는 패턴"이라는 것 정도만 알아두시면 됩니다.
mapStateToProps 는 리덕스 스토어의 상태를 조회해서 어떤 것들을 props 로 넣어줄지 정의합니다.
mapDispatchToProps 는 액션을 디스패치하는 함수를 만들어서 props로 넣어줍니다.
export default connect(mapStateToProps,mapDispatchToProps)(CakeContainer);
npm i --save redux-devtools-extention
import { composeWithDevTools } from "redux-devtools-extension";
// applyMiddleware를 composeWithDevTools로 감싸준다.
const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(logger))
);