我们上一篇文章梳理了flux的架构模式和redux,这章我们来梳理react-redux.顺便补充一下redux开发过程中的规范或者说惯例
一.actionsType.js的补充
在上个章节中我们说actionsType.js只是为了代码美观和报错,实际上这个确实只有这两点用途,但是我们没有说具体原因
- 代码美观:我们在进行dispatch的时候会传递一个type,上一篇也说了这是规范,调用必须这样,那我们这个type传递的字符串会越来越多,因为我们代码逻辑复杂之后我们的dispatch会非常的多,那我们在使用的时候就要提出来放在actionsType中,然后定义一些变量来储存这些字符串,我们调用dispatch的时候直接传递这些变量就可以了
- 代码报错:我们在调用dispatch的时候因为传递参数时字符串,在代码检查逻辑中不管传的有没有对不对都不会报错的,但是我们就这样糊里糊涂的去调用,我们定义变量储存字符串之后,再进行调用的时候,就会发现我们如果写错了,编辑器或者代码检查逻辑就会报错提示我们,我们引用了一个没有定义的变量,这样更利于我们代码编写的容错,毕竟项目大了代码多了谁也没法保证我们用不写错
二.react-redux
因为react-redux实际上就是一个redux的react专用版本而已,所以整体的思想与逻辑都是没有改变的,包括使用中的reducer和action这些store中的逻辑都是没有变的,唯一改变的就是在使用redux的时候有所不同,我们刨除相同的部分,相同的可以去react梳理之redux中先看redux原理,只梳理一下与redux不同的使用方式
-
Provider组件
-
connect
:这里边有两个函数mapStateToProps
和mapDispatchToProps
作为参数传入,详细看下边的解释 -
useSelector
-
useDispatch
Provider
组件的使用
在react-redux的使用中,我们不需要用subscribe去订阅了,摆脱了在每个组件都需要去订阅的麻烦逻辑,我们只需要用Provider组件来包裹我们需要使用store数据的标签,或者说ui组件,就可以在组件或者标签内部使用store
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
import { Provider } from 'react-redux'
import store from './redux/store'
ReactDOM.render(
<Provider store={store}>
<MyRootComponent />
</Provider>,
rootEl
)
<provider>
使组件层级中的 connect() 方法都能够获得 Redux store。正常情况下,根组件应该嵌套在 中才能使用 connect() 方法。也就是说只有给根组件嵌套了一层这个组件,我们才能正常的在子组件之中使用react-redux
connect
的使用
import React from 'react';
import { connect } from 'react-redux'
const mapStateToProps = (state: RootState) => {
return {
language: state.language
}
}
const mapDispatchToProps = (dispatch) => {
return {
changeLanguage: () => dispatch({
type:'LANGUAGE',
code:'vus'
})
}
}
class App extends Component {
render() {
const { language,changeLanguage } = this.props
return (
<div>
{ language }
<div onClcik={ changeLanguage }>改变language为vus</div>
</div>
)
}
}
//函数式组件的唯一区别就是一下这点
function App (props){
const { language,changeLanguage } = props
return (
<div>
{ language }
<div onClcik={ changeLanguage }>改变language为vus</div>
</div>
)
}
export default connect(mapStateToProps,mapDispatchToProps)(App)
这里边有两个概念性的东西,就是
mapStateToProps
和mapDispatchToProps
,这俩实际上不是固定名称,而是我们习惯性的可读性高的命名方式,这两个都是回调函数,且接受参数值
mapStateToProps
:这个就是接受state的函数,在connect中传入第一个参数就是获取state的函数,回调函数的参数里可以直接去state,通过筛分我们挑出来我们需要订阅使用的值,return返回对象,例如return { language: state.language }
,这样我们就可以在APP组件中直接使用this.props来取用state了,为什么是App中呢,因为我们要给哪个组件传递props,就会在connect的返回函数中传入哪个组件:connect(mapStateToProps,mapDispatchToProps)(App
)
mapDispatchToProps
:这个是用来给我们的组件传递封装好的dispatch方法的,我们由代码可以看到,跟state的传递没什么差别,甚至使用也没什么差别,而且很好理解
useSelector
使用
这个其实是后来的东西,给我们解决了一部分平常开发中烦恼的问题,我们用connect写着写着代码发现,太麻烦了,我几乎得在任何一个地方进行这样的两个函数的封装然后再传递进去,从而取到state和dispatch,比redux肯定是简单了,但是远远不够我们的要求,于是就出现了这个东西,我们不用再去包裹传递,直接就在开头的时候给取出来
import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
export default function App() {
const dispatch = useDispatch()
const current = useSelector((state) => {
return state.current
})
const changeCurrent = ()=> {
dispatch({
type: 'SWITCH_CURRENT',
current: '修改后的current'
})
}
return (
<div>
子组件
<h3>{current}</h3>
<button onClick={changeCurrent}>修改current</button>
</div>
)
}
state不再需要connect去包裹传递,直接就用useSelector给暴露出来,给我们的组件直接使用,也不用再想是类组件还是函数式组件了
useDispatch
使用
这个更简单,这个就是说直接给dispatch暴漏出来了而已,实际上react-redux的传递dispatch也没有做什么东西,只是给dispatch自动引入然后让封装dispatch的时候使用罢了,换成了useDispatch反而是退化了一步,只进行了引入,因为在我们的redux中这个dispatch是需要我们引入store来拿到的,但是现在经过provider在根组件传递之后,我们不需要引入了,但是还是需要以useDispatch暴露一下才可以
总结:实际上react-redux只是与redux的使用习惯上有所区别,我们仔细分析会发现,实际上根本上还是订阅发布者模式,订阅发布模式我们了解了之后,这个只不过就是去熟悉使用方式罢了,有什么问题的,欢迎交流