combineReducers
创建recommendProductsReducer.ts
interface RecommendProductsState {loading: boolean;error: string | null,productList: any[]}const defaultState: RecommendProductsState = {loading: true,error: null,productList: []}const recommendProductsReducer = (state = defaultState, action) => {return state}export default recommendProductsReducer
使用combineReducers
在store.ts中使用 combineReducers 将多个 reducers 整合
import { createStore,combineReducers } from 'redux'import languageReducer from './language/languageReducer'import recommendProductsReducer from './recommendProducts/recommendProductsReducer'const rootReducer = combineReducers({language: languageReducer,recommendProducts: recommendProductsReducer})const store = createStore(rootReducer)export type RootState = ReturnType<typeof store.getState>export type AppDispatch = typeof store.dispatchexport default store
原先只用 store.state 就能访问的数据,现在要再加一层 rootReducer 的属性
const language = useSelector((state) => state.language.language)const languageList = useSelector((state) => state.language.languageList)
创建actionCreator
export const FETCH_RECOMMEND_PRODUCTS_START = "FETCH_RECOMMEND_PRODUCTS_START"export const FETCH_RECOMMEND_PRODUCTS_SUCCESS = "FETCH_RECOMMEND_PRODUCTS_SUCCESS"export const FETCH_RECOMMEND_PRODUCTS_FAIL = "FETCH_RECOMMEND_PRODUCTS_FAIL"interface FetchRecommendProductsStartAction {type: typeof FETCH_RECOMMEND_PRODUCTS_START}interface FetchRecommendProductsSuccessAction {type: typeof FETCH_RECOMMEND_PRODUCTS_SUCCESSpayload: any}interface FetchRecommendProductsFailAction {type: typeof FETCH_RECOMMEND_PRODUCTS_FAILpayload: any}export type RecommendProductsAction =| FetchRecommendProductsStartAction| FetchRecommendProductsSuccessAction| FetchRecommendProductsFailActionexport const fetchRecommendProductsStartActionCreator = ():FetchRecommendProductsStartAction => {return {type: FETCH_RECOMMEND_PRODUCTS_START}}export const fetchRecommendProductsSuccessActionCreator = (data):FetchRecommendProductsSuccessAction => {return {type: FETCH_RECOMMEND_PRODUCTS_SUCCESS,payload: data}}export const fetchRecommendProductsFailActionCreator = (error):FetchRecommendProductsFailAction => {return {type: FETCH_RECOMMEND_PRODUCTS_FAIL,payload: error}}
修改 recommendProductsReducer.ts
import { FETCH_RECOMMEND_PRODUCTS_FAIL, RecommendProductsAction, FETCH_RECOMMEND_PRODUCTS_START, FETCH_RECOMMEND_PRODUCTS_SUCCESS } from './recommendProductsActions';interface RecommendProductsState {loading: boolean;error: string | null,productList: any[]}const defaultState: RecommendProductsState = {loading: true,error: null,productList: []}const recommendProductsReducer = (state = defaultState, action: RecommendProductsAction) => {switch(action.type){case FETCH_RECOMMEND_PRODUCTS_START:return {...state, loading: true}case FETCH_RECOMMEND_PRODUCTS_SUCCESS:return {...state, loading: false, productList: action.payload}case FETCH_RECOMMEND_PRODUCTS_FAIL:return {...state, loading: false, error: action.payload}default:return state}}export default recommendProductsReducer
在组件中定义 mapStateToProps 和 mapDispatchToProps,用 connect 连接
const mapStateToProps = (state: RootState) => {return {loading: state.recommendProducts.loading,error: state.recommendProducts.error,productList: state.recommendProducts.productList}}const mapDispatchToProps = (dispatch) => {return {fetchStart: () => {dispatch(fetchRecommendProductsStartActionCreator())},fetchSuccess: (data) => {dispatch(fetchRecommendProductsSuccessActionCreator(data))},fetchFail: (error: string) => {dispatch(fetchRecommendProductsFailActionCreator(error))}}}export const HomePage = connect(mapStateToProps,mapDispatchToProps)(withTranslation()(HomePageComponent))
重新定义props类型
type PropsType = WithTranslation& ReturnType<typeof mapStateToProps>& ReturnType<typeof mapDispatchToProps>class HomePageComponent extends React.Component<PropsType, State> {constructor(props){super(props)this.state = {loading: true,error: null,productList: []}}
使用 props 上的 state 和 dispatch
此时不需要再使用state, 因为都绑定到 props 上了
class HomePageComponent extends React.Component<PropsType> {// 移除了constructorasync componentDidMount(){this.props.fetchStart()try {const {data} = await axios.get('/api/productCollections')this.props.fetchSuccess(data)}catch(error: any) {this.props.fetchFail(error.message)}}render() {const { t } = this.propsconst {productList, loading, error} = this.props// ...}}
