React学习系列(一)之redux使用

287 阅读3分钟

在vue之中有VueX做全局的状态管理,在react之中有两种方案:1. redux; 2. mobx

redux的特点

在使用之前,需要先了解一下redux的特点。

  1. redux是为了解决页面间数据(state)共享而生的,因此其内部数据应该很容易地被每个页面/组件获取;
  2. 单一数据源:整个应用的state都存在于一个store(数据仓库)中;
  3. state是只读的:唯一改变state的方法只能是通过触发(dispatch)action来产生;
  4. 为了描述action如何改变state,需要reducers函数

简单的redux示例

根据以上特点来编写一个简单的redux来明白其工作流程:以简单的加减为例

//html结构
//注意onclick函数:特点3 通过dispatch action来改变state
<button onclick="store.dispatch({type:'JIAN',n:2})">-</button>
<span id="countDisplay">5</span>
<button onclick="store.dispatch({type:'JIA',n:3})">+</button>

//script
const createStore = (reducers) =>{
    // 特点2:单一数据源,只存在于函数内部
    let state = null
    
    const Listeners = []
    const subscribe = (listener) => Listeners.push(listener)
    
    // 特点3
    const dispatch = (action) =>{
        // 特点4
        state = reducers(state, action)
        //模拟渲染视图
        Listenrs.forEach(listener=> listener()
    }
    
    const getState = () => state
    
    return{
        getState,
        dispatch,
        subscribe
    }
}

const countState = {
    count: 5
}

//reducer函数,输入state,action,根据action的类型来改变内部的state
const click = (state, action) =>{
    if(!state){
        return countState
    }
    
    switch(action.type){
        case 'JIAN':
            return{
                ...state,
                count: state.count - action.n
            }
        case 'JIA':
            return {
                ...state,
                count: state.count + action.n
            }
        default:
            return state
    }
}

//创建store
const store = createStore(click)

//获取store内部state的数据
const renderCount = () => {
    countDisplay.innerHTML = store.getState().count
}

//订阅渲染界面的函数
store.subscribe(renderCount)

以上就上一个简单的redux工作流程:

  1. reducers负责干活:根据action.type来改变内部state
  2. dispatch作为中介,当有交互发生的时候,dispatch就派发动作并让reducers开始干活。注意:在这里我们直接写的是store.dispatch({type:'JIAN',n:2}),我们也可以写一个函数,只要它返回的结果是action类型的,如store.dispatch(login(paylaod:any)),方便传参
  3. getState负责获取state数据,当数据发生改变后界面就开始渲染

flux架构

可以看出redux的工作流程就是依据flux架构来的

redux使用

react-redux, redux-thunk(异步中间件), connected-react-router(路由注入state中)

完整的案例见GitHub:github.com/Simplyme082…

创建三部分文件:

  1. store.tsx 生成数据仓库
  2. action文件夹,管理不同组件对应的action
  3. reducer文件夹,管理不同组件对应的reducer,其中index.tsx管理所有的reducer,并将其合并成一个reducer

项目文件中:

//Login为登录组件
connect(mapStatetoProps, mapDispatchToProps)(Login)

从字面意思上可以看出这是一个State和dispatch与props的mapping关系。

  1. mapStatetoProps: 这里的State是指redux中的state,而props是当前组件的props。数据是从redux中传入组件的。从下方代码可以看出这里是取出redux中的完整/部分state值存入组件中
//此属性写在组件文件中
const mapStatetoProps = (state: combinedState): usersActionState => {
    return state.users
}
  1. mapDispatchToProps: 这里就是指把dispatch传入当前组件的props中。而在此例中应用了异步数据,因此要使用redux-thunk中间件可以让我们手动决定什么时候调用dispatch函数以达到异步的目的。
//此属性写在action文件夹内对应的文件中
export const mapDispatchToProps=(dispatch:Dispatch)=>({
    login(payload:any){
        dispatch(startLogin())
        request(payload).then(res=>{
            dispatch(loginSuccess(res))
        }).catch((err:any)=>{
            console.log(err)
            dispatch(loginFailed())
        })
    }
})

注:视图的更新react会自动帮我们完成

总结

react-redux的使用还是比较复杂的,因此对于过页面共享数据的情景下才会使用,对于日常一些小项目无需使用如此繁杂的redux。