前文说到,纯粹的Redux操作并不是很方便,于是react专门出了一个react-redux库来管理这个问题。来看看他的示意图:
connect
react-redux库有效的将react组件和redux结合了起来,它的思想是套一个容器,用容器进行对redux的交互,而真正的react ui 组件则通过count组件给它传的props进行数据的交互,它会传给ui组件两个值,一个是redux中所有保存的状态,一个是用于操作装态的各种方法。于是对上文的代码进行最终的修改:
store文件的修改
+ const combine = combineReducers({
+ showTagsReducer
+ })
- export default createStore(showTagsReducer)
+ export default createStore(combine)
ShowTags组件修改
+ import {connect} from "react-redux";
- componentDidMount() {
- store.subscribe(()=>{
- this.setState(()=>{
- return {...this.state,isShow:!this.state.isShow}
- })
- })
- }
- changeState = ()=>{
- const {isShow} = this.state
- store.dispatch(showTagsAction(isShow))
- }
+ changeState = ()=>{
+ const {isShow} = this.state
+ this.props.showTagsAction(isShow)
+ this.setState({isShow: !isShow});
+ }
+ return (
...
- {store.getState() ? tagsArr.map(item=><li key={item.id}>{item.name}</li>) : "空"}
+ {this.props ? tagsArr.map(item=><li key={item.id}>{item.name}</li>) : "空"}
)
+ export default connect(state=>({isShow:state.showTagsReducer}),{
+ showTagsAction
+ })(index)
index.js
//对APP组件进行包裹,代码如下:
<Provider store={store}>
<App/>
</Provider>
新加的变量的解释:
connect函数是一个科里化函数,第一个括号中它把redux的状态和改变装态的方法传给了组件,第二个括号中传它要改变的组件名称。因此,connect的完整api写法应该如下
const VisibleTodoList = connect(
mapStateToProps, //这里传对应的状态,用回调函数的形式传入
mapDispatchToProps //这里传对应改变状态的各种action
)(TodoList)
<Provide>标签用于统一将store作为参数传入,使它作为state对象很快就能传到需要对象上,并且在state改变的时候进行渲染。
redux在hooks中的使用
新的hooks发布之后,由于我们可以用自定义的hooks来对数据进行操作,所以很大程度上redux都不需要了。但是对于老的代码,有时候需要进行redux重构,所以这边写一下redux在hooks中的写法: 首先分析一下,redux到目前为止学到的,它到底干了什么?我的理解是,他用store存储了一个状态,暴露给reactcomponent一个接口,只接受一个action对象对状态进行改变,然后根据action对象的方法,用reducer进行想对应的操作,这个就是redux的本质。那么hooks有哪几个api可以实现redux的操作?
- 我们需要一个变量,能像Provider一样将store对象数据以直接开辟一个虫洞的方式传给对象
- 我们需要一个方法,能将store对象引入,并且像connect方法一样提供一个读接口,一个写接口
第一个需求我们用useContext解决,第二个我们用useReducer方法解决。由此,给出以下代码
//引入需要的useContext,useReducer
import React, {createContext, useContext, useReducer} from "react";
//定义初始的context对象,这边因为模拟redux,就取名了redux
const Redux = createContext({});
const initState = {
name:"xiaoznz",
n:10
}
//跟redux中一样,我们需要提前写好一个reducer方法,从而根据action给出的type进行相应的操作
const reducer = (state,action)=>{
const {type,data} = action
switch (type){
case "addNum":
return {...state,n:state.n+data};
case "deleteNum":
return {...state,n:state.n+data};
default:
return state;
}
}
// 用hooks模拟redux
function App(){
//useReducer的实际应用,分别提供了一个读接口:state,一个写接口:dispath
const [state,dispatch] = useReducer(reducer,initState)
return (
<>
//context的使用,让数据能够通过特定的方法直接往下传输
<Redux.Provider value={{state,dispatch}}>
<ShowNum/>
</Redux.Provider>
</>
)
}
function ShowNum(){
//解析得到的接口
const {state,dispatch} = useContext(Redux)
return (
<div>
Redux的数据是:{state.n},用户的名字是:{state.name}
<hr/>
//对得到的方法进行dispath操作,改变数据的状态
<button onClick={()=>{dispatch({type:"addNum",data:1})}}>+1</button>
<button onClick={()=>{dispatch({type:"deleteNum",data:1})}}>-1</button>
</div>
)
}
export default App;
由此,redux的基础篇基本上讲完了。