在React中使用redux
步骤:
1.在React项目中安装 Redux库:
`npm install redux`
2.在src文件夹中创建store文件夹,并在store文件夹中创建4个文件(上一篇所讲的拆分文件, 但这里要注意,导入和导出方式不在是之前的CommonJS的方式,而是要换成ES6的export、import)
3.使用redux
第2行:导入 store
第9行:利用store中存储的值,对组件的state进行初始化
第13行:订阅store中值的变化,当变化时,更新组件的state
第21行:点击事件,派发action,更改store中的值
第29行: 将值展示在页面上
总结:
1.在某个页面使用redux, 需要用到store,所以要import store
2.该页面的值都是放在state中的,所以用store中的存储的值对组件的state进行初始化
3.对数据进行订阅
4.当页面卸载时,取消订阅
5.当发生事件时,拿到store调用dispatch变更数据
重构React中使用Redux的代码
上面讲了如何在React中使用Redux,但是发现,每次在一个组件中使用redux时,就要重复一遍上面的1-5的步骤,这样就太麻烦了,我们要对这样的代码进行重构,这里我们使用高阶组件的方式来简化代码,高阶组件可以对组件渲染过程进行拦截,我们就将这些冗余部分代码放到高阶组件中
如果我们自己封装高阶组件也是可以的,但实际开发中都是用一个现成的三方库 react-redux
使用react-redux:
1.安装react-redux:
npm install react-redux
2.让全局都可以访问到store:
根据前面的总结的可以知道,当我们需要在某个组件中使用redux时,就要导入store,当有很多组件要使用时,每次都导入。所以要让全局都能访问到store,就不用每次都要导入了。
只需要通过Provider包裹根组件App,就可以让所有组件都可以访问到store
3.通过connect共享数据、修改数据:
第2行: 导入connect
第29行: 创建一个函数,该函数用于传递给connect函数作为参数,会在connect库中被调用,被调用的同时connect库会将store中存储的值传参给该函数,该函数的返回值是一个对象,用来映射store中存储的哪些值要被共享出去
第33行: 创建一个函数,该函数用于传递给connect函数作为参数,会在connect库中被调用,被调用的同时connect库会将dispatch传参给该函数,该函数的返回值是一个对象,用来将dispatch方法共享出去
第40行: connect本身是一个函数,它返回一个高阶组件。 调用connect时,传递29行 和 33行 创建的函数进去,返回一个高阶组件,返回的高阶组件再调用时,传递About组件进去, 因为是高阶组件,作用就是对传入的组件做一些处理,所以内部会做类似下面的操作:
<About {...this.props} {...obj}> 这样就将这些东西,全部以props属性的形式传递给About组件
第19行: 在页面上显示数据。 因为40行的操作,使得store中存储的数据,已经以props的形式传递给了组件,所以可以直接从props中取值
第7~13行: 事件函数。 因为40行的操作,使得组件的props中已经有了dispatch方法,所以可以直接从props中取到方法,对数据进行操作
总结:
当不使用react-redux时,每次使用redux,都要在当前组件做重复的操作:导入store、用store中的值初始化组件的state、订阅数据、取消订阅、手动使用store的dispatch变更数据。
而使用了react-redux时,不需要到处导入store、不需要订阅数据,取消订阅、 不要手动使用store的dispatch变更数据。我们只需要编写 两个函数,作为参数,传递给connect函数,再将当前组件传递给connect函数返回的高阶组件即可
redux-thunk:
实际开发中,store中的存储的值,一般都是来自于网络请求。 我们就得在成功获取数据后,调用dispatch给store赋值。 那么这个请求的方法写在哪里呢?
简单的想到,写在某个组件中,在该组件中调用网络请求,成功后调用dispatch给store赋值
该数据是要存储在store中的,写在某个组件中请求这个数据,不是很合理,应该直接在redux中请求数据赋值给store比较合理。我们想把第8行的请求代码挪到redux中,这样我们在组件中只需要调用一下dispatch,派发某个可以发送请求的获取数据的action,就可以让store中有值了。
所以,在redux中我们创建一个用来请求的action,代码如下:
这样我们在组件中就只需要调用一下这个dispatch派发这个可以发送请求的acton,store就有值了。
但是真的是这样吗? 其实不然,发现执行在27行时,返回action对象的函数就已经执行完毕了,且返回了一个undefined, 等33行的return执行时,已经没用了,dispatch action这个过程早结束了。
所以这样的写法是不行的。
那如果我们在组件中调用dispatch派发的action不是一个对象,而是一个函数的话,并且这个函数又将dispatch传入作为参数,那么不就可以在这个action函数中进行网络请求了吗?当请求成功后返回数据,再调用传进来的dispatch派发这个网络请求成功后返回的数据,不就可以实现在redux中通过网络请求获取数据了么 但是正常情况下dispatch只能派发对象,并不能派发函数,这里就需要用到一个中间件:redux-thunk
1.安装redux-thunk
npm install redux-thunk
2.使用redux-thunk
使用redux-thunk对store进行增强,这样创建出来的store就可以派发函数了
编写一个产生action的函数,不过这个函数产生的action不在是一个对象,而是一个函数