- redux-thunk:
비동기 작업을 처리할 때 가장 많이 사용하는 미들웨어이며, 객체가 아닌 함수 형태의 액션을 디스패치 할 수 있게 해줌.
- redux-saga:
redux-thunk 다음으로 가장 많이 사용되는 비동기 작업 관련 미들웨어 라이브러리 입니다, 특정 액션이 디스패치 되었을때 정해진 로직에 따라 다른 액션을 디스패치 시키는 규칙을 작성하여 비동기 작업을 처리하게 할 수있게 해줌.
THUNK란?
- 특정 작업을 나중에 할 수 있도록 미루기 위해 함수 형태로 감싼 것
//일반 적으로
const addOne =x => x+1
console.log(addOne(1)) 하면
정답은 2가 나온다.
//thunk 적용
const addOne =x => x+1
function addOneThunk(x){
const thunk =()=>addOne(x)
return thunk
}
const fn = addOneThunk(1);
setTimeout(() => {
const value = fn();
console.log(value);
}, 1000);
이렇게 하면 1 이 출력되고 1초 이따가 2가 출력됨.
syntax:
const sampleThunk = () => (dispatch,getState) =>{
//현 상태를 참조 할 수 있고,
// 새 액션을 디스패치 할 수도 있음.
}
설치:
//설치 yarn add redux-thunk / npm install redux-thunk
스토어에 연결
import ReduxThunk from "redux-thunk" const store = createStore(rootReducer, applyMiddleware(ReduxThunk))
비동기 디스패치 함수를 추가
//1초 뒤에 increase 혹은 decrease 함수를 디스패치함 export const increaseAsync = () => (dispatch) => { setTimeout(() => { dispatch(increase()) }, 1000) } export const decreaseAsync = () => (dispatch) => { setTimeout(() => { dispatch(decrease()) }, 1000) }
Actions 호출
import React from "react" import { connect } from "react-redux" import { increaseAsync, decreaseAsync } from "../modules/counter" import Counter from "../components/Counter" const CounterContainer = ({ number, increaseAsync, decreaseAsync }) => { return <Counter number={number} onIncrease={increaseAsync} onDecrease={decreaseAsync} /> } export default connect( (state) => ({ number: state.counter, }), { increaseAsync, decreaseAsync } )(CounterContainer)
1 초 간격으로 +1이 되고 -1 이됨
import axios from "axios"
export const getPost = (id) => axios.get(`https://jsonplaceholder.typicode.com/posts/${id}`)
export const getUsers = (id) => axios.get(`https://jsonplaceholder.typicode.com/users`)
//리듀서 만들기
import { handleActions } from "redux-actions"
import * as api from "../lib/api"
import createRequestThunk from "../lib/createRequestThunk"
//액션타입을 선언
// 한 요청당 세 개를 만들어야 함
const GET_POST = "sample/GET_POST"
const GET_POST_SUCCESS = "sample/GET_POST_FAILURE"
const GET_POST_FAILURE = "sample/GET_POST_FAILURE"
const GET_USERS = "sample/GET_USERS"
const GET_USERS_SUCCESS = "sample/GET_USERS_SUCCESS"
const GET_USERS_FAILURE = "sampe/GET_USERS_FAILURE"
//Thunk 함수 생성
//Thunk 함수 내부에서 시작할떄, 성공했을때, 실패했을때 액션들을 디스패치
export const getPost = createRequestThunk(GET_POST, api.getPost)
export const getUsers = createRequestThunk(GET_USERS, api.getUsers)
초기 상태를 선언합니다
요청의 로딩 중 상태는 loading 이라는 객체를 관리함
const initialState = {
loading: {
GET_POST: false,
GET_USERS: false,
},
post: null,
users: null,
}
const sample = handleActions(
{
[GET_POST]: (state) => ({
...state,
loading: {
...state.loading,
GET_POST: true, //요청 시작
},
}),
[GET_POST_SUCCESS]: (state, action) => ({
...state,
post: action.payload,
}),
[GET_POST_FAILURE]: (state, action) => ({
...state,
loading: {
...state.loading,
GET_POST: false, //요청 완료
},
}),
[GET_USERS]: (state) => ({
...state,
loading: {
...state.loading,
GET_USERS: true, //요청 시작
},
}),
[GET_USERS_SUCCESS]: (state, action) => ({
...state,
users: action.payload,
}),
[GET_USERS_FAILURE]: (state, action) => ({
...state,
loading: {
...state.loading,
GET_USERS: false,
},
}),
},
initialState
)
export default sample
import React from "react"
import { connect } from "react-redux"
import Sample from "../components/Sample"
import { getPost, getUsers } from "../modules/sample"
const { useEffect } = React
const SampleContainer = ({ getPost, getUsers, post, users, loadingPost, loadingUsers }) => {
useEffect(() => {
const fn = async () => {
try {
await getPost(1)
await getUsers(1)
} catch (e) {
console.log(e) //에러 조회
}
}
fn()
}, [getPost, getUsers])
return (
<Sample post={post} users={users} loadingPost={loadingPost} loadingUsers={loadingUsers} />
)
}
export default connect(
({ sample, loading }) => ({
post: sample.post,
users: sample.users,
loadingPost: loading["sample/GET_POST"],
loadingUsers: loading["sample/GET_USERS"],
}),
{ getPost, getUsers }
)(SampleContainer)
어떻게 되는지 새로고침을 하긴 했는데 비동기처리 되어 페이지가 로딩후 출력되는 기능이다.
안녕하세요^^ 저 궁금한게 저런 이미지 뭘로 찍으신거에요? GIF처럼?