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.dispatch
export 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_SUCCESS
payload: any
}
interface FetchRecommendProductsFailAction {
type: typeof FETCH_RECOMMEND_PRODUCTS_FAIL
payload: any
}
export type RecommendProductsAction =
| FetchRecommendProductsStartAction
| FetchRecommendProductsSuccessAction
| FetchRecommendProductsFailAction
export 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> {
// 移除了constructor
async 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.props
const {productList, loading, error} = this.props
// ...
}
}