Today I Learned ... react.js
🙋♂️ Reference Book
🙋 My Dev Blog
리액트를 다루는 기술 DAY 18
- Redux Middleware
API 서버를 연동할 때는 API 요청에 대한 state도 잘 관리해야 한다.
$ yarn add redux react-redux redux-actions
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;
리듀서 함수가 한개지만, combineReducers를 해주었다.
-> 여러개가 아닐 때도 rootReducer로 export 해주기위해 combineReducers({})를 해주자.
redux의 createStore()로 스토어 생성 후,
react-redux의 Provider 컴포넌트의props
로 store을 넘겨줌.
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css'
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import rootReducer from './modules';
const store = createStore(rootReducer);
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
components/Counter.js
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 { 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);
+) useSelector, useDispatch 사용 ver.
import { increase, decrease } from "../modules/counter";
import Counter from "../components/Counter";
import { useSelector, useDispatch } from "react-redux";
const CounterContainer = () => {
const number = useSelector(state => state.counter);
const dispatch = useDispatch();
return (
<Counter number={number}
onIncrease={() => dispatch(increase)}
onDecrease={() => dispatch(decrease)}
/>
);
};
export default CounterContainer;
import CounterContainer from "./containers/CounterContainer";
function App() {
return (
<div>
<CounterContainer/>
</div>
);
}
export default App;
리액트 미들웨어는 액션을 디스패치 했을 때 리듀서에서 처리하기에 앞서, 사전에 지정된 작업을 실행한다.
= 액션과 리듀서의 중간자 역할.
lib/loggerMiddleware.js
const loggerMiddleware = store => next => action => {
// 기본 구조
};
export default loggerMiddleware;
loggerMiddleware은 3중 중첩함수로 구성되어 있다.
(화살표 함수를 연달아서 사용하였음.)
const loggerMiddleware = function loggerMiddleware(store) {
return function (next) {
return function (action) {
};
};
};
store
은 리덕스 스토어 객체를,action
은 디스패치된 액션을 가리킴.next
는 함수형태로, dispatch()와 비슷한 역할을 함.const loggerMiddleWare = store => next => action => {
console.group(action && action.type); // 액션 타입으로 log를 그룹화
console.log('이전 상태', store.getState());
console.log('action', action);
next(action); // 다음 미들웨어(or 리듀서)에게 전달
console.log('다음 상태', store.getState()); // 업데이트된 state
console.groupEnd(); // 그룹화 끝
}
export default loggerMiddleWare;
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import './index.css'
import { applyMiddleware, createStore } from 'redux';
import { Provider } from 'react-redux';
import rootReducer from './modules';
import loggerMiddleWare from './lib/loggerMiddleware';
const store = createStore(rootReducer, applyMiddleware(loggerMiddleWare));
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
-> redux 라이브러리의 applyMiddleware
함수의 인자로 미들웨어를 넣어줌.
createStore() 함수
createStore(루트리듀서, applyMiddleware(미들웨어));
console.group()
- mdn 문서 참조
- console.groupEnd()가 나올 때 까지 들여쓰기 되어서 콘솔에 출력됨.