Redux 미들웨어
액션 -> (미들웨어) -> 리듀서 -> 스토어
리덕스에서 dispatch 를 하면 action이 리듀서로 전달되고, 리듀서는 새로운 state 를 반환한다. 근데 미들웨어를 사용하면 이 과정 사이에 우리가 하고싶은 작업들을 넣을 수 있음.
ex) 만약 counter 프로그램에서 더하기 버튼을 클릭했을 시, 바로 +1 을 더하지 않고 3초를 기다렸다가 +1 이 되도록 구현하려면 미들웨어를 사용하지 않고는 구현 불가능.
이는 dispatch가 되자마자 action이 리듀서로 달려가서 새로운 state를 반환해버리기 때문.
여기서 3초를 기다리는 작업 -> 미들웨어가 해주는 역할.
미들웨어를 사용하는 이유는 서버와의 통신을 위해서 사용하는 것이 대부분이고, 많이 사용되는 것은 Redux-thunk, saga 등이 있다.
Thunk
리덕스에서 가장 많이 사용하는 미들웨어 중 하나로, thunk를 사용하면 우리가 dispatch 할 때 객체가 아닌 함수를 dispatch 할 수 있게 해줌. 즉, dispatch(함수)를 할 수 있게 되는 것.
dispatch(함수) → 함수실행 → 함수안에서 dispatch(객체)
1. thunk 함수를 만들기 : createAsyncThunk
- reduxToolkit 내장 API
2. createSlice > extraReducer 에 thunk 등록
3. dispatch
4. 테스트
counter.js
import { createSlice } from "@reduxjs/toolkit";
import { createAsyncThunk } from "@reduxjs/toolkit";
// 2개의 input
// (1) 이름 : 의미는 크게 없음
// (2) 함수
// 청크 이름에는 언더바 두개가 들어감
export const __plusNumber = createAsyncThunk(
"PLUS_NUMBER_WAIT",
(payload, thunkAPI) => {
// 수행하고 싶은 동작 : 3초를 기다리게 할 예정
setTimeout(() => {
thunkAPI.dispatch(plusNumber(payload));
}, 3000);
}
);
export const __minusNumber = createAsyncThunk(
"MINUS_NUMBER_WAIT",
(payload, thunkAPI) => {
setTimeout(() => {
thunkAPI.dispatch(minusNumber(payload));
}, 3000);
}
);
// 초기 상태 값
const initialState = {
number: 0,
};
// action creator, reducer 둘 다 들어있음
const counterSlice = createSlice({
name: "counter",
initialState,
reducers: {
plusNumber: (state, action) => {
state.number = state.number + action.payload;
},
minusNumber: (state, action) => {
state.number = state.number - action.payload;
},
},
});
export default counterSlice.reducer;
export const { plusNumber, minusNumber } = counterSlice.actions;
App.js
import logo from "./logo.svg";
import "./App.css";
import { useState } from "react";
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { __plusNumber, __minusNumber } from "./modules/counter";
function App() {
const globalnumber = useSelector((state) => state.counter.number);
const [number, setNumber] = useState(0);
const dispatch = useDispatch();
const onPlusButtonClickHandler = () => {
dispatch(__plusNumber(+number));
};
const onMinusButtonClickHandler = () => {
dispatch(__minusNumber(+number));
};
return (
<div>
{globalnumber}
<input type="number" onChange={(e) => setNumber(e.target.value)} />
<br />
<button onClick={onPlusButtonClickHandler}>+</button>
<button onClick={onMinusButtonClickHandler}>-</button>
</div>
);
}
export default App;
'React' 카테고리의 다른 글
[React] React Query (0) | 2023.07.05 |
---|---|
[React] custom hooks (0) | 2023.07.05 |
[React] instance 와 interceptor (0) | 2023.07.04 |
[React] Fetch 와 Axios (0) | 2023.07.04 |
[React] 비동기 통신 axios(patch) (0) | 2023.07.04 |