脚本宝典收集整理的这篇文章主要介绍了react项目使用redux入门-6-redux-thunk中间件处理异步请求,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
src/index.tsx
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux' // react-redux 利用上下文context,提供的数据组件Provider
import 'antd/dist/antd.css'
import './index.css'
import App from './App'
import 'i18n'
import store from 'redux/store'
ReactDOM.render(
<React.StrictMode>
{/* 使用Provider, 并加载 数据仓库 store, 就可以在全局范围内使用store */}
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
)
ListPage
组件中请求数据
import { Component } from 'react'
import { connect } from 'react-redux'
import { ThunkDispatch } from 'redux-thunk' // ThunkDispatch<S,E,A> 为了支持函数类型的action,提供dispatch的类型
import { RootState } from 'redux/store'
import { ActionsProductProps, fetchProductsActionCreator } from 'redux/product/actions'
const mapStateToProps = ({ product }) => product
// const mapStateToProps = ({ product }: RootState) => {
// return {
// loading: product.loading,
// productList: product.productList
// }
// }
const mapDispatchToProps = (dispatch: ThunkDispatch<RootState, unknown, ActionsProductProps> ) => {
fetchProduct : () => dispatch(fetchProductsActionCreator())
}
class ListPageComponent extends Component<ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>, any> {
componentDidMount() {
const { fetchProduct } = this.props
fetchProduct()
}
render(){
const { productList, loading } = this.props
return loading? <div>正在加载……</div>:(
<div>
{
productList.map(item => <p key={item.id}>{item.name}</p>)
}
</div>
)
}
}
export const ListPage = connect(mapStateToProps, mapDispatchToProps)(ListPageComponent)
Header
组件中使用
import { Component } from 'react'
import { withRouter, RouteComponentProps } from 'react-router-dom'
import { MenuInfo } from 'rc-menu/lib/interface'
import { nanoid } from 'nanoid'
// 使用react-redux
import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import store, { RootState } from 'redux/store'
import { addLanguageActionCreator, changeLanguageActionCreator } from 'redux/language/actionCreators'
const mapStateToProps = (state: RootState) => {
return {
lng: state.language.lng,
languageList: state.language.languageList
}
}
const mapDispatchToProps = (dispatch: Dispatch) => {
return {
addLanguageDispatch: (language: { code: string, language: string }) => {
dispatch(addLanguageActionCreator(language))
}
changeLanguageDispatch: (lng: 'en'|'zh') => {
dispatch(changeLanguageActionCreator(lng))
}
}
}
class HeaderComponent extends Component<RouteComponentProps & ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>>{
render(){
const { history, lng, languageList, addLanguageDispatch, changeLanguageDispatch } = this.props
/* meun 的点击事件 */
const oprateLanguage = ( e: MenuInfo ) => {
if(e.key !== 'new'){
changeLanguageDispatch(e.key)
}else{
addLanguageDispatch({code: `lng${nanoid()}`, language: '新语种'})
}
}
const menu = (
<Menu>
<Menu.Item key='new' onClick={oprateLanguage}>
添加新语言
</Menu.Item>
{languageList.map(language => (
<Menu.Item key={language.code} onClick={oprateLanguage}>
{language.language}
</Menu.Item>
))}
</Menu>
)
return (
<div>
<Typography.Text className='mr40'>让旅游更幸福</Typography.Text>
<Dropdown overlay={menu}>
<Button>
{languageList.find(language => language.code === lng)?.language}
<GlobalOutlined />
</Button>
</Dropdown>
</div>
)
}
}
export const Header = connect(mapStateToProps, mapDispatchToProps)(withRouter(HeaderComponent))
store
数据封装
src/redux
、src/redux/language
src/redux/store.ts
、src/redux/language/actionCreators.ts
,src/redux/language/reducers.ts
mkdir src/redux src/redux/language
touch src/redux/language/actionCreators.ts src/redux/language/reducer.ts
touch src/redux/product/actions.ts src/redux/product/reducer.ts
store.ts
import { createStore, combineReducers, applyMiddleware } from 'redux'
import languageReducer form './language/reducer.ts'
import productReducer form './product/reducer.ts'
import thunk form 'redux-thunk'
// 使用 combineReducers方法,连接多个reducer
const rootReducer = combineReducers({
language: languageReducer,
product: productReducer
})
// redux-thunk 使用thunk中间件,使得redux的action除了对象形式,还是支持函数类型
const store = createStore(rootReducer, applyMiddleware(thunk))
// 使用ts的条件类型 ReturnType<T>,T:函数类型。 获取函数返回值的类型
export type RootState = ReturnType<typeof store.getState>
export default store
product/actions.ts
、product/reducers.ts
actions.ts
// 使用redux-thunk,支持函数类型的action,这个action的类型:ThunkAction<R,S,E,A>
import { ThunkAction } from 'react-thunk'
import axios from 'axios'
import { RootState } from 'redux/store'
// fetch_start 主要是用来控制loading, 开始发接口,loading值为true
export const FETCH_START = 'product/fetch_start'
// fetch_success 主要用来 接口数据成功,将数据data存入store
export const FETCH_SUCCESS = 'product/fetch_success'
export const FETCH_FAIL = 'product/fetch_fail'
interface ActionFetchStartProps { type: typeof FETCH_START}
interface ActionFetchSuccessProps { type: typeof FETCH_SUCCESS, payload: any}
interface ActionFetchFailProps { type: typeof FETCH_FAIL }
export type ActionsProductProps = ActionFetchStartProps | ActionFetchSuccessProps | ActionFetchFailProps
// actionCreator
export const fetchStartActionCreator = (): ActionFetchStartProps => ({ type: FETCH_START})
export const fetchSuccessActionCreator = (data:any):ActionFetchSuccessProps => ({ type: FETCH_SUCCESS, payload: data })
export const fetchFailActionCreator = ():ActionFetchFailProps => ({ type: FETCH_FAIL })
// 函数类型的action
export const fetchProductsActionCreator = (): ThunkAction<void, RootState, unknown, ActionsProductProps>=> async (dispatch, getState) => {
dispactch(fetchStartActionCreator())
try{
const { data } = await axios.get('/api/products')
dispatch(fetchSuccessActionCreator(data))
}catch{
dispatch(fetchFailActionCreator())
}
}
reducer.ts
import { ActionsProductProps, FETCH_START, FETCH_SUCCESS, FETCH_FAIL } from './actions.ts'
interface ProductState {
loading: boolean,
productList: any[]
}
const defaultState: ProductState = {
loading: false,
productList: []
}
export default (state = defaultState, action:ActionsProductProps ) => {
switch (action.type) {
case FETCH_START:
return { ...state, loading: true }
case FETCH_SUCCESS:
return { ...state, loading: false, tourists: action.payload }
case FETCH_FAIL:
return { ...state, loading: false }
default:
return state
}
}
language/actions.ts
、language/reducers.ts
actions.ts
/* 用常量定义action.type,减少代码敲错 */
export const ADD_LANGUAGE = 'language/add'
export const CHANGE_LANGUAGE = 'language/change'
/* action的类型申明 */
const AddActionProps = {
type: typeof ADD_LANGUAGE,
payload: { code: string, language: string }
}
const ChangeActionProps = {
type: typeof CHANGE_LANGUAGE,
payload: 'zh' | 'en'
}
export type LanguageActionProps = AddActionProps | ChangeActionProps
/* 用工厂模式创建action */
export const addLanguageActionCreator = (language: {code: string, language: string}):ADD_LANGUAGE => {
return {
type: ADD_LANGUAGE,
payload: language
}
}
export const changeLanguageActionCreator = (lng: 'zh' | 'en'):CHANGE_LANGUAGE => {
return {
type: CHANGE_LANGUAGE,
payload: lng
}
}
2. `reducer.ts`
import { ADD_LANGUAGE, CHANGE_LANGUAGE, LanguageActionProps } from './actions'
export interface LanguageState {
lng: 'zh' | 'en',
languageList: {code: string, language: string}[]
}
const defaultStoreState: LanguageState = {
lng: 'zh',
languageList: [{ code: 'zh', language: '中文'}, { code: 'en', language: 'English'}]
}
export default (state = defaultStoreState, action:LanguageActionProps) => {
switch (action.type) {
case CHANGE_LANGUAGE:
return { ...state, lng: action.payload }
case ADD_LANGUAGE:
return { ...state, languageList: [...state.languageList, action.payload] }
default:
return state
}
}
以上是脚本宝典为你收集整理的react项目使用redux入门-6-redux-thunk中间件处理异步请求全部内容,希望文章能够帮你解决react项目使用redux入门-6-redux-thunk中间件处理异步请求所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。