combineReducers

将 homePage 改为使用redux

创建recommendProductsReducer.ts

  1. interface RecommendProductsState {
  2. loading: boolean;
  3. error: string | null,
  4. productList: any[]
  5. }
  6. const defaultState: RecommendProductsState = {
  7. loading: true,
  8. error: null,
  9. productList: []
  10. }
  11. const recommendProductsReducer = (state = defaultState, action) => {
  12. return state
  13. }
  14. export default recommendProductsReducer

使用combineReducers

在store.ts中使用 combineReducers 将多个 reducers 整合

  1. import { createStore,combineReducers } from 'redux'
  2. import languageReducer from './language/languageReducer'
  3. import recommendProductsReducer from './recommendProducts/recommendProductsReducer'
  4. const rootReducer = combineReducers({
  5. language: languageReducer,
  6. recommendProducts: recommendProductsReducer
  7. })
  8. const store = createStore(rootReducer)
  9. export type RootState = ReturnType<typeof store.getState>
  10. export type AppDispatch = typeof store.dispatch
  11. export default store

原先只用 store.state 就能访问的数据,现在要再加一层 rootReducer 的属性

  1. const language = useSelector((state) => state.language.language)
  2. const languageList = useSelector((state) => state.language.languageList)

创建actionCreator

  1. export const FETCH_RECOMMEND_PRODUCTS_START = "FETCH_RECOMMEND_PRODUCTS_START"
  2. export const FETCH_RECOMMEND_PRODUCTS_SUCCESS = "FETCH_RECOMMEND_PRODUCTS_SUCCESS"
  3. export const FETCH_RECOMMEND_PRODUCTS_FAIL = "FETCH_RECOMMEND_PRODUCTS_FAIL"
  4. interface FetchRecommendProductsStartAction {
  5. type: typeof FETCH_RECOMMEND_PRODUCTS_START
  6. }
  7. interface FetchRecommendProductsSuccessAction {
  8. type: typeof FETCH_RECOMMEND_PRODUCTS_SUCCESS
  9. payload: any
  10. }
  11. interface FetchRecommendProductsFailAction {
  12. type: typeof FETCH_RECOMMEND_PRODUCTS_FAIL
  13. payload: any
  14. }
  15. export type RecommendProductsAction =
  16. | FetchRecommendProductsStartAction
  17. | FetchRecommendProductsSuccessAction
  18. | FetchRecommendProductsFailAction
  19. export const fetchRecommendProductsStartActionCreator = ():FetchRecommendProductsStartAction => {
  20. return {
  21. type: FETCH_RECOMMEND_PRODUCTS_START
  22. }
  23. }
  24. export const fetchRecommendProductsSuccessActionCreator = (data):FetchRecommendProductsSuccessAction => {
  25. return {
  26. type: FETCH_RECOMMEND_PRODUCTS_SUCCESS,
  27. payload: data
  28. }
  29. }
  30. export const fetchRecommendProductsFailActionCreator = (error):FetchRecommendProductsFailAction => {
  31. return {
  32. type: FETCH_RECOMMEND_PRODUCTS_FAIL,
  33. payload: error
  34. }
  35. }

修改 recommendProductsReducer.ts

  1. import { FETCH_RECOMMEND_PRODUCTS_FAIL, RecommendProductsAction, FETCH_RECOMMEND_PRODUCTS_START, FETCH_RECOMMEND_PRODUCTS_SUCCESS } from './recommendProductsActions';
  2. interface RecommendProductsState {
  3. loading: boolean;
  4. error: string | null,
  5. productList: any[]
  6. }
  7. const defaultState: RecommendProductsState = {
  8. loading: true,
  9. error: null,
  10. productList: []
  11. }
  12. const recommendProductsReducer = (state = defaultState, action: RecommendProductsAction) => {
  13. switch(action.type){
  14. case FETCH_RECOMMEND_PRODUCTS_START:
  15. return {...state, loading: true}
  16. case FETCH_RECOMMEND_PRODUCTS_SUCCESS:
  17. return {...state, loading: false, productList: action.payload}
  18. case FETCH_RECOMMEND_PRODUCTS_FAIL:
  19. return {...state, loading: false, error: action.payload}
  20. default:
  21. return state
  22. }
  23. }
  24. export default recommendProductsReducer

在组件中定义 mapStateToProps 和 mapDispatchToProps,用 connect 连接

  1. const mapStateToProps = (state: RootState) => {
  2. return {
  3. loading: state.recommendProducts.loading,
  4. error: state.recommendProducts.error,
  5. productList: state.recommendProducts.productList
  6. }
  7. }
  8. const mapDispatchToProps = (dispatch) => {
  9. return {
  10. fetchStart: () => {
  11. dispatch(fetchRecommendProductsStartActionCreator())
  12. },
  13. fetchSuccess: (data) => {
  14. dispatch(fetchRecommendProductsSuccessActionCreator(data))
  15. },
  16. fetchFail: (error: string) => {
  17. dispatch(fetchRecommendProductsFailActionCreator(error))
  18. }
  19. }
  20. }
  21. export const HomePage = connect(mapStateToProps,mapDispatchToProps)(withTranslation()(HomePageComponent))

重新定义props类型

  1. type PropsType = WithTranslation
  2. & ReturnType<typeof mapStateToProps>
  3. & ReturnType<typeof mapDispatchToProps>
  4. class HomePageComponent extends React.Component<PropsType, State> {
  5. constructor(props){
  6. super(props)
  7. this.state = {
  8. loading: true,
  9. error: null,
  10. productList: []
  11. }
  12. }

使用 props 上的 state 和 dispatch

此时不需要再使用state, 因为都绑定到 props 上了

  1. class HomePageComponent extends React.Component<PropsType> {
  2. // 移除了constructor
  3. async componentDidMount(){
  4. this.props.fetchStart()
  5. try {
  6. const {data} = await axios.get('/api/productCollections')
  7. this.props.fetchSuccess(data)
  8. }catch(error: any) {
  9. this.props.fetchFail(error.message)
  10. }
  11. }
  12. render() {
  13. const { t } = this.props
  14. const {productList, loading, error} = this.props
  15. // ...
  16. }
  17. }