21-在组件中使用异步动作(redux-thunk)

Time: 20200130

安装必要的包

yarn add axios
yarn add redux-thunk

配置中间件: redux-thunk

store.js

import { createStore, applyMiddleware } from 'redux'
import { rootReducer } from './rootReducer'
import thunk from 'redux-thunk'
import logger from 'redux-logger'
import { composeWithDevTools } from 'redux-devtools-extension'

const store = createStore(rootReducer, 
    composeWithDevTools( applyMiddleware(logger, thunk)
    )
 )

export default store

redux-thunk也是一个中间件,需要通过applyMiddleware使用。

异步Action Creator

修改userActions.js

import 
{ FETCH_USER_REQUEST, 
  FETCH_USER_SUCCESS, 
  FETCH_USER_FAILURE
} 
from './userTypes'
import axios from 'axios'
/**
 * Action Creator接收数据,通过参数的方式接收,然后存到action对象中
 * reducer不用操心数据的问题,只要定义好逻辑即可
 * 即,reducer是纯函数
 */

// 三个Action Creator函数,均为同步Action
export const fetchUserRequest = () => {
    return {
        type: FETCH_USER_REQUEST
    }
}
// 这些参数需要通过外部传入
export const fetchUserSuccess = users => {
    return {
        type: FETCH_USER_SUCCESS,
        payload: users
    }
}
export const fetchUserFailure = error => {
    return {
        type: FETCH_USER_FAILURE,
        payload: error
    }
}

// 异步Action Creator
// 被thunk接管,所以返回一个函数
// 返回的函数不要求是纯函数
export const fetchUserAsync = () => {
    return (dispatch) => {
        // 在真正读取数据前先告知要开始获取数据了
        dispatch(fetchUserRequest)
        axios.get('https://jsonplaceholder.typicode.com/users')
            .then(response => {
                // 分发到同步Action 
                const users = response.data
                dispatch(fetchUserSuccess(users))
            })
            .catch(error => {
                const errorMessage = error.message
                dispatch(fetchUserFailure(errorMessage))
            })
    }
}
// 只要dispatch就可以把数据存储到action.payload

同步异步Action Creator都写在一起,同步Action Creator是为异步服务,最后只需要暴露异步Action Creator即可。

UserContainer.js

import React, { useEffect } from 'react'
import { connect } from 'react-redux'
import { fetchUserAsync } from '../redux'

// 解构props
function UserContainer({userData, fetchUsers}) {
    // dispatch only once
    useEffect(() => {
        fetchUsers()
    }, [])

    return userData.loading 
        ? <h2>Loading</h2> 
        : (userData.error 
            ? <h2>{userData.error}</h2>
            : (<div>
                <h2>Users List</h2>
                <div>
                    {userData && userData.users && userData.users.map(user => <p>{user.name}</p>)}
                </div>
                
               </div>))
                   
}

const mapStateToProps = (state, ownProps) => {
    return {
        userData: state.user
    }
}

const mapDispatchToProps = (dispatch, ownProps) => {
    return {
        fetchUsers: () => dispatch(fetchUserAsync())
    }
}

export default connect(mapStateToProps, 
    mapDispatchToProps)
(UserContainer)

END.

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容