手记

【九月打卡】第十六天 Redux

课程:React18 系统精讲

章节:Redux

讲师:阿莱克斯刘

课程内容

第一个任务,我们需要为store创建与home页面相对应的状态state,推荐产品列表数据
第二个任务,在新建推荐产品列表state的时候,我们也要准备好相应的reducer
第三个任务,需要为 获取 api 数据 创建 action。
第四个任务,在主页中连接store,并且分发action
这节课的的四个任务看似简单,但实际上相当于是整个第七章的综合,请同学们一定要注意跟紧课程节奏。

任务一与任务二
其实第一个任务和第二个任务是互相关联的,因为state是reducer的输出,所以当我们新建了reducer,那么store中的state也会自动被更新。所以,我们可以同时来处理第一、和第二两个任务,先来创建产品推荐列表的reducer。

既然是一个全新的状态模块,那么我们可以在redux下新建一个文件夹来存放相关的代码,文件夹名称recommendProducts。 然后新建文件,recommendProductsReducer.ts。

首先,来创建一个空的reducer函数,这个很简单,就是一个匿名函数,参数接受store中的旧状态state,以及动作事件action。return的数据就是新state,我们暂时使用参数state。

接下来,要考虑的就是reducer的输出格式,也就是产品推荐数据state的数据结构的接口。
产品推荐的数据其实很简单,不就是产品推荐列表吗,变量名称使用productionList,类型any类型列表。

除此以外,因为我们将会处理的是api数据,所以我们还需要考虑对api请求的控制,所以,添加两个额外的属性,loading flag 以及 error flag。其实这两个flag的类型与上节课的定义是一样的,loading 是bolean类型,error是stirng和null的混合类型。

所以,我们可以使用这个interface来定义初始化的默认产品推荐数据,而loading一开始设置为true,表示正在获取数据,而error设置为null,表示暂时没有收到错误信息。

然后,在reducer函数中把初始化数据传递给参数state

接下来,我们来把这个reducer添加到store中。请同学们注意,接下来的代码需要使用一个额外的redux函数来处理。

请同学们打开store.ts,这个额外的redux函数就是combineReducers。我们从reudx中引入这个函数。

然后还要把刚刚创建的recommendProductsReducer也引入进来

接下来,我们需要通过使用combineReducers函数,把languageReducer和recommendProductsReducer捆绑起来。向combineReducers中传入languageReducer和recommendProductsReducer,不过这里的数据要以对象的形式来传递。

然后,把捆绑后的state数据对象保存在本地变量中,名称叫做rootReducer,顾名思义,他就是所有reducer的集合体。这里的命名rootReducer是一个约定俗成的名称,同学们最好遵守,显得专业一点,当然你非要胡诌一个名字也可以,你开心就好。然后,把rootReducer传递给createStore函数,使用rootReducer来创建sotre的数据state。

把鼠标移动到RootState类型上,我们可以看到现在的state已经从原本的languuage变成了包含languuage和recommendProducts两个字段的数据类型了。

因为store的数据结构已经更改了,所以同学们不要忘记我们得回到header组件,修改一下store数据的获取。打开header.tsx,vs code已经帮我们标注出错误的代码了。

首先是第27行,对当前语言的选择,我们在useSelector中使用state对象的脸时结构来看看state中都有些什么数据。

State中有language和recommendProducts两个字段的数据,对于当前语言,我们当然要选择language。然后继续,在language这个大的对象中还包含着两小的数据段,当前语言就是这个state.language.language。为什么是连续的两个language,这个问题留给同学们思考一下,相信同学们很快就能找出答案。而languageList显而易见,就是state.language.languageList。

好了,报错消失,这个文件应该是没有问题了。

同样的思路,我们来修正一下类组件版本的 header,打开header.class文件。

我们会到store,继续代码。

第三个任务
接下来,就是我们的第三个任务,创建产品推荐列表的 action。创建action,首先我们得创建他的文件,recommendProductsAction.ts。

接下来,需要考虑的就是action的类型。我们需要哪些action呢?因为是从api调取数据,所以我们可以从AXAJ请求的角度来考虑问题。

首先,我们肯定得知道API请求什么开始,所以第一个action就是请求开始,action 类型可以叫做FETCH_RECOMMEND_PRODUCTS_START, 表示正在接受推荐信息
所以,第二、和第三个action就分别描述api调用成功与失败这两种情况了。
接下来,仿照上节课的内容,我们来给每个action定义接口

第一个是正在调用推荐信息api,这个action的类型type 就是typeof FETCH_RECOMMEND_PRODUCTS_START,它是没有payload数据的

第二个是 推荐信息api调用成功,这个action的类型type 是typeof FETCH_RECOMMEND_PRODUCTS_SUCCESS,它是没有payload就是api调用成功以后返回的数据,因为是后端数据,我也不知道数据类型,直接写个any代替吧,等真正获得数据以后再说,这样可以保证代码的灵活性。

第三个是推荐信息api调用失败,这个action的类型type 是typeof FETCH_RECOMMEND_PRODUCTS_FAIL,它是没有payload就是api调用失败以后返回的数据,我们也可以使用any作为类型。

最后,把以上三个action混合一下,输出action的总类型,类型名称RecommendProductAction ,方便我们一会在reducer中使用

接下来,就是action的最后一个部分,也是最重要的部分,我们来完成action的创建工程,action creator

第一个action creator自然就是创建正在接受推荐信息action了。代码很简单,函数名称fetchRecommendProductStartActionCreator ,retun的aciton就是
FetchRecommendProductStartAction

第二个是,推荐信息api调用成功 action。代码也不复杂,函数名称fetchRecommendProductSuccessActionCreator,retun的aciton的类型是FetchRecommendProductSuccessAction。接受api成功后返回的数据作为参数,而api返回数据会传递给payload。

最后一个就是创建推荐信息api调用失败这个action了。函数名称fetchRecommendProductFailActionCreator,retun的aciton的类型是FetchRecommendProductFailAction。接受api失败后返回的错误信息将会作为参数传递进来,错误信息绑定给payload。

action代码全部完成,回到reducer,我们来处理一下action。首先引入一下action类型,

然后,使用RecommendProductAction类型来定义reducer的第二个参数,然后跟languageReducer一样,使用一个switch语句,我们来判定一下传入action的类型。

第一个case FETCH_RECOMMEND_PRODUCTS_START,只需要更新一下loading的状态。
第二个case FETCH_RECOMMEND_PRODUCTS_SUCCESS,在这个case中,我们需要更新loading的状态为false,加载api数据,因为api调用成功,所以error设置为null。
第三个case FETCH_RECOMMEND_PRODUCTS_FAIL,这是调用错误的case,当然我们需要取得error数据,而loading的状态也应该设置为false
ok,现在与redux相关的代码全部结束了,接下来,要开始使用了。回到主页,homepage.tsx。还记得我们上一章使用过的redux高阶函数connect吗?接下来我们就要使用这个高阶组件了。

然后,我们在home文件的最后一行,使用connect函数连接组件和redux store。注意connect函数需要连续使用两个小括号,第二个小括号放入组件。

接下来,我们来处理redux state和dispatch的映射连接函数。
第一个函数映射state,mapStateToProps, 参数state是从store中过来的,我们来定义一下类型。

从store中引入RootState。

然后,分别映射三个数据,

第一,推荐列表的loading状态,
第二,推荐列表的error信息
第三,推荐列表数据
接下来,我们还需要连接dispatch,分发action。不过先让我们引入推荐列表的三个aciton,start,fail 以及 success

接着,完成mapDispatchToProps函数,我们将会映射三个函数,fetchRecommendProductStart,fetchRecommendProductSuccess,fetchRecommendProductFail。

接下来,我们把mapStateToProps和mapDispatchToProps的类型放在组件的props定义中。

连接redux的最后一步就是把mapStateToProps和mapDispatchToProps当作参数,放入connect函数的第一个小括号中。

好了,redux连接起来了,我们可以开始使用了。

既然组件状态以及被redux取代了,那么我们也没有必要继续保留组件state相关代码了,所以,首先删掉state接口类型,然后删掉构造函数。

接着处理componentDidMount,保留异步async操作,函数开始的时候,首先通过 this.props 发送 fetchRecommendProductStart action。如果api请求成功,则发送fetchRecommendProductSuccess action,在并且把api返回数据作为payload传递给reducer。如果请求失败,则会被catch语句捕获,发送fetchRecommendProductFail action,error message会被当作payload传递给reducer。

接下来,我们修复jsx渲染代码。删除与组件状态state相关的代码,而我们的productList、loading、以及error的状态将会从props中取得。

保存代码,运行网站,网站打开,好了,现在我们主页的数据以及状态现在全部都是由redux接管了,于是,我们主页的设计模式从mvc转换到redux了,我们本节课也接近尾声了。经过本节课的学习,可能有些同学会说,不对啊,阿老师,怎么感觉越改越复杂了?怎么感觉原本使用mvc的架构还更容易理解和维护一点。关于这一点,同学你说的没错,我们的主页转为redux以后思路反而没那么清晰了。

但是,换个角度思考,一旦我们reudx中产品推荐的数据需要同步显示在其他页面或组件中,那么效率是非常高的,我们只需要通过一次api调用就可以完成数个组件的数据同步了。

关于mvc与redux的争论,我们先暂时搁置,在接下来的课程我们会慢慢讨论细节。现在请同学们跟着课程进度学习下节课的内容,使用reudx-thunk中间件处理事件的异步分发。

0人推荐
随时随地看视频
慕课网APP