react项目使用redux入门-5-使用combineReducers连接多个reducer。一个store,多个reducer
场景:切换语言、请求产品列表
-
src/index.tsximport 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({/* 使用Provider, 并加载 数据仓库 store, 就可以在全局范围内使用store */} , document.getElementById('root') ) -
ListPage组件中请求数据import { Component } from 'react' import { connect } from 'react-redux' import { RootState } from 'redux/store.ts' import { fetchStartActionCreator, fetchSuccessActionCreator, fetchFailActionCreator } from 'redux/tourist/actions' const mapStateToProps = ({ product }: RootState) => product const mapDispatchToProps = (dispatch: Dispatch) => { return { fetchStart: () => dispatch(fetchStartActionCreator()), fetchSuccess: (data: []) => dispatch(fetchSuccessActionCreator(data)), fetchFail: () => dispatch(fetchFailActionCreator()), } } class ListPageComponent extends Component& ReturnType , any> { async componentDidMount() { const { fetchStart, fetchSuccess, fetchFail } = this.props fetchStart() try { const { data } = await axios.get('/api/touristRoutes') fetchSuccess(data) } catch (e) { fetchFail() } } render(){ const { productList } = this.props return ( { productList.map(item =>) } } export const ListPage = connect(mapStateToProps, mapDispatchToProps)(ListPageComponent){item.name}
) } -
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.lng, languageList: state.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& ReturnType >{ 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 = ( ) return ( ) } } 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.tsstore.ts
import { createStore, combineReducers } from 'redux' import languageReducer form './language/reducer.ts' import productReducer form './product/reducer.ts' // 使用 combineReducers方法,连接多个reducer const rootReducer = combineReducers({ language: languageReducer, product: productReducer }) const store = createStore(rootReducer) // 使用ts的条件类型 ReturnType,T:函数类型。 获取函数返回值的类型 export type RootState = ReturnType export default store - product:-
product/actions.ts、product/reducers.ts
actions.ts
// 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 })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:-
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 } } - 新建目录: