반응형
- 미들웨어가 디스패치 앞뒤에 코드를 추가할 수 있게 해준다.
- 미들웨어가 여러개이면 미들웨어가 순차적으로 실행된다.
- 2단계가 있음
- 스토어를 만들때 미들웨어를 설정하는 부분
- {createStore, applyMiddleware} from redux
- 디스패치가 호출될떄 실제로 미들웨어를 통과하는 부분
- 스토어를 만들때 미들웨어를 설정하는 부분
- dispatch 메소드를 통해 store로 가고있는 액션을 가로채는 코드
직접 만들어보기
store.js
import { applyMiddleware, createStore } from 'redux'
import todoApp from './reducers/reducer'
function middleware1(store){
console.log("middleware1", 0);
return(next) => {
console.log("middleware1", 1);
return action => {
console.log('middleware1', 2);
const returnValue = next(action);
console.log('middleware1', 3);
return returnValue;
}
};
}
const store = createStore(todoApp, applyMiddleware(middleware1));
export default store;
middleware1 0
store.js:7 middleware1 1
store.js:9 middleware1 2
store.js:11 middleware1 3
store.js:9 middleware1 2
store.js:11 middleware1 3
store.js:9 middleware1 2
store.js:11 middleware1 3
//input 추가 후
middleware1 2
store.js:11 middleware1 3
middleware 2개 생성
import { applyMiddleware, createStore } from 'redux'
import todoApp from './reducers/reducer'
function middleware1(store){
console.log("middleware1", 0);
return(next) => {
console.log("middleware1", 1,next); ///////////////////////--------(1)
return action => {
console.log('middleware1', 2);
const returnValue = next(action); ///////////////////////--------(4)
console.log('middleware1', 3);
return returnValue;
}
};
}
function middleware2(store){
console.log("middleware2", 0);
return(next) => {
console.log("middleware2", 1,next);
return action => { ///////////////////////--------(2)
console.log('middleware2', 2);
const returnValue = next(action); ///////////////////////--------(3)
console.log('middleware2', 3);
return returnValue;
}
};
}
const store = createStore(todoApp, applyMiddleware(middleware1,middleware2));
export default store;
middleware1의 next의 의미는 middleware2의 (2)를 의미한다.
middleware1을 통과해서 middleware2로 넘어가서 (2)을 실행하려고 하고 실행하다가 next를 만다면 dispatch가 되고 다시 returnValue가 되면서 다시 middleware1에서 returnValue로 들어온다.
보통 직접 middleware을 만드는경우는 없으며 라이브러리가 나와있음
redux-devTools
npm i redux-devtools-extension -D
const store = createStore(todoApp, composeWithDevTools(applyMiddleware()));
export default store;
extension redux- devtools 깔기
redux-thunk
- 리덕스 미들웨어
- 리덕스 비동기 처리를 위한 라이브러리
- 액션 생성자를 활용하여 비동기 처리
- 액션 생서자가 액션을 리턴하지 않고 함수를 리턴함
npm i redux-thunk
store.js
import { applyMiddleware, createStore } from 'redux'
import todoApp from './reducers/reducer'
import {composeWithDevTools} from 'redux-devtools-extension';
import thunk from 'redux-thunk';
//applyMiddleware는 함수를 리턴할떄만 반응하고 객체를 리턴할때는 그대로 동작한다.
const store = createStore(todoApp, composeWithDevTools(applyMiddleware(thunk)));
export default store;
비동기 로직에서 수정하기
getUsers라는 함수를 액션 생성함수로 바꾸고 함수리턴하는 방식으로 수정하기!
actions.js
export function getUsersThunk(){
//함수로 리턴
//dispatch는 원래 container에서 처리하고 있는데 이제는 액션 생성하는쪽에서 실행시킨다.
return async (dispatch)=>{
try {
dispatch(getUsersStart());
const res = await axios.get('<https://api.github.com/users>');
dispatch(getUsersSuccess(res.data)); ;
}catch(error){
dispatch(getUsersFail(error));
}
}
}
UserListConatiner.jsx
import { useCallback } from "react";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux"
import UserList from "../components/UserList"
import { getUsersThunk } from "../redux/actions";
export default function UserListContainer(){
const users = useSelector((state) => state.users.data);
const dispatch = useDispatch();
const getUsers = useCallback(()=> {
dispatch(getUsersThunk())
},[dispatch]);
return <UserList users={users} getUsers={getUsers} />
}
redux-promise-middleware
npm i redux-promise-middleware
store.js
설정
import { applyMiddleware, createStore } from 'redux'
import todoApp from './reducers/reducer'
import {composeWithDevTools} from 'redux-devtools-extension';
import thunk from 'redux-thunk';
import promise from 'redux-promise-middleware'
const store = createStore(todoApp, composeWithDevTools(applyMiddleware(thunk,promise)));
export default store;
payload로 promise를 지정해주면 type을 변조해서 dispatch를 한다. promise객체가 생성 된 직후에 pending 상태가 되며 정상적으로 완료되면 fullfilled 가 되고 비정상적이면 rejected가된다. 각각 그것에 맞게 action type을 생성해주어야한다.
actions.js
import axios from "axios";
//......
const GET_USERS = 'GET_USERS'
export const GET_USERS_PENDING = 'GET_USERS_PENDING'
export const GET_USERS_FULLFILLED = 'GET_USERS_FULLFILLED'
export const GET_USERS_REJECTED = 'GET_USERS_REJECTED'
export function getUsersPromise(){
return {
type: GET_USERS,
payload: async() => {
const res = await axios.get('<https://api.github.com/users>');
return res.data;
}
}
}
UserListContainer.jsx
import { useCallback } from "react";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux"
import UserList from "../components/UserList"
import { getUsersPromise, getUsersThunk } from "../redux/actions";
export default function UserListContainer(){
const users = useSelector((state) => state.users.data);
const dispatch = useDispatch();
const getUsers = useCallback(()=> {
dispatch(getUsersPromise())
},[dispatch]);
return <UserList users={users} getUsers={getUsers} />
}
users.js
import { GET_USERS_FAIL, GET_USERS_FULLFILLED, GET_USERS_PENDING, GET_USERS_REJECTED, GET_USERS_START, GET_USERS_SUCCESS } from "../actions";
const initialState = {
loading: false,
data: [],
error: null
};
export default function users(state = initialState, action) {
if(action.type === GET_USERS_START || action.type === GET_USERS_PENDING){
return {
...state,
loading: true,
error: null,
};
}
if(action.type === GET_USERS_SUCCESS){
return {
...state,
loading: false,
data: action.data,
};
}
if(action.type === GET_USERS_FULLFILLED){
return {
...state,
loading: false,
data: action.payload,
};
}
if(action.type === GET_USERS_FAIL){
return {
...state,
loading: false,
error: action.error,
};
}
if(action.type === GET_USERS_REJECTED){
return {
...state,
loading: false,
error: action.payload,
};
}
return state;
}
반응형
'개발(라이브러리,프레임워크) > react.js & react native' 카테고리의 다른 글
redux-thunk (0) | 2022.02.03 |
---|---|
redux-devtools (0) | 2022.02.02 |
Async Action (0) | 2022.01.31 |
Redux 를 React에 연결(라이브러리x) (0) | 2022.01.21 |
Redux 개요, 사용 (0) | 2022.01.20 |