React - 6장 : 컴포넌트 반복
React - 7장 : 컴포넌트의 LifeCycle
React - 8장 : React Hooks 총정리
React - 12장 : immer를 사용하여 더 쉽게 불변성 유지하기
React - 13장 : 리액트 라우터로 SPA 개발하기
React - 18장 : 리덕스 미들웨어를 통한 비동기 작업 관리
18-1. 작업 환경 준비
- 새 리액트 프로젝트를 생성
// 프로젝트 생성
yarn create react-app learn-redux-middleware
// 라이브러리 설치
yarn add redux react-redux redux-actions
- 바로 전에 리덕스파트에서 counter 리덕스 모듈 작성했던 것 처럼 코드 작성
// modules/counter.js
import { createAction, handleActions } from 'redux-actions';
const INCREASE = 'counter/INCREASE';
const DECREASE = 'counter/DECREASE';
export const increase = createAction(INCREASE);
export const decrease = createAction(DECREASE);
const initialState = 0;
const counter = handleActions(
{
[INCREASE]: state => state + 1,
[DECREASE]: state => state - 1
},
initialState
);
export default counter;
- 루트 리듀서를 생성
// modules/index.js
import { combineReducers } from 'redux';
import counter from './counter';
const rootReducer = combineReducers({
counter
});
export default rootReducer;
- src 디렉터리의 index.js에서 스토어를 생성한 후, Provider로 리액트 프로젝트에 리덕스를 적용
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import rootReducer from './modules';
const store = createStore(rootReducer);
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
- 카운터 컴포넌트와 카운터 컨테이너 컴포넌트를 만든다. 프레젠테이셔널 컴포넌트는 components 디렉터리에 저장하고, 컨테이너 컴포넌트는 containers 디렉터리에 저장
// components/Counter.js
import React from 'react';
const Counter = ({ onIncrease, onDecrease, number }) => {
return (
<div>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</div>
);
};
export default Counter;
// containers/CounterContainer.js
import React from 'react';
import { connect } from 'react-redux';
import { increase, decrease } from '../modules/counter';
import Counter from '../components/Counter';
const CounterContainer = ({ number, increase, decrease }) => {
return (
<Counter number={number} onIncrease={increase} onDecrease={decrease} />
);
};
export default connect(
state => ({
number: state.counter
}),
{
increase,
decrease
}
)(CounterContainer);
- App에서 CounterContainer를 렌더링
import React from 'react';
import CounterContainer from './containers/CounterContainer';
const App = () => {
return (
<div>
<CounterContainer />
</div>
);
};
export default App;
- 그럼 이제 작업환경세팅은 다 끝났고 미들웨어부분으로 들어가보자
18-2. 미들웨어란?
- 리덕스 미들웨어는 액션을 디스패치했을 때 리듀서에서 이를 처리하기에 앞서 사전에 지정된 작업들을 실행한다. 미들웨어는 액션과 리듀서 사이의 중간자라고 볼 수 있다.
- 액션이 디스패치될 때마다 액션의 정보와 액션이 디스패치되기 전후의 상태를 콘솔에 보여 주는 로깅 미들웨어를 예시로 만들어 보겠다.
- src 디렉터리에 lib 디렉터리를 생성하고, 그 안에 loggerMiddleware.js 파일을 생성
// lib/loggerMiddleware.js
const loggerMiddleware = store => next => action => {
// 미들웨어 기본 구조
};
export default loggerMiddleware;
// 일반 function 키워드로 풀어서 쓴다면 다음과 같은 구조
const loggerMiddleware = function loggerMiddleware(store) {
return function(next) {
return function(action) {
// 미들웨어 기본 구조
};
};
};
- 미들웨어는 결국 함수를 반환하는 함수를 반환하는 함수
- 위의 코드를 보면 여기에 있는 함수에서 파라미터로 받아 오는 store는 리덕스 스토어 인스턴스를,
action은 디스패치된 액션을 가리킨다.
- next 파라미터는 함수 형태이며, store.dispatch와 비슷한 역할을 합니다.
- next(action)을 호출하면 그다음 처리해야 할 미들웨어에게 액션을 넘겨주고,
만약 그다음 미들웨어가 없다면 리듀서에게 액션을 넘겨준다는 것이다.
- 이번에 만들 미들웨어는 다음 정보를 순차적으로 콘솔에 보여 준다..
- 이전 상태
- 액션 정보
- 새로워진 상태
// loggerMiddleware.js
const loggerMiddleware = store => next => action => {
console.group(action && action.type); // 액션 타입으로 log를 그룹화함
console.log('이전 상태', store.getState());
console.log('액션', action);
next(action); // 다음 미들웨어 혹은 리듀서에게 전달
console.log('다음 상태', store.getState()); // 업데이트된 상태
console.groupEnd(); // 그룹 끝
};
export default loggerMiddleware;
- 미들웨어를 스토어(index.js)에 적용
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import rootReducer from './modules';
import loggerMiddleware from './lib/loggerMiddleware';
const store = createStore(rootReducer, applyMiddleware(loggerMiddleware));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
'Frontend > ReactJS(완)' 카테고리의 다른 글
추가) React redux-toolkit 리덕스 쉽게 쓰는 비법 (0) | 2023.03.07 |
---|---|
React - 19장 : 코드 스플리팅(완) (0) | 2023.03.02 |
React - 17장 : 리액트 리덕스 실습 예제(React-Redux) (0) | 2023.02.28 |
React - 16장 : 리덕스(Redux) 라이브러리의 이해 (0) | 2023.02.28 |
추가) React에서의 PWA (0) | 2023.02.24 |
댓글