redux于react的关联

571 阅读3分钟

前文说到,纯粹的Redux操作并不是很方便,于是react专门出了一个react-redux库来管理这个问题。来看看他的示意图:

react-redux模型图.png

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的操作?

  1. 我们需要一个变量,能像Provider一样将store对象数据以直接开辟一个虫洞的方式传给对象
  2. 我们需要一个方法,能将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的基础篇基本上讲完了。