redux执行流程和常用库?

459 阅读3分钟

根据官方的话来说:Redux 是 JavaScript 状态容器,提供可预测化的状态管理。里面可以存储各种状态。可能是这样的

{
    loading:true,
    userData:[]
}

它就是一个普普通通的JavaScript对象。但是你想要修改它,可不太容易.你需要编写一个action。

Action

action是什么呢? **action 是一个用于描述已发生事件的普通对象。**它也是对象,但是需要一个type字段。

{
    type:ADD_TODO,
    payload:{text:0}
}

但是在一般会写成一个函数

const addTodo = () =>({
    type:ADD_TODO,
     payload:{text:0}
})

这样做的目标是确保视图不用直接修改store里面的数据,所有修改行为都要集中处理。那提交的action交给reduce处理。

reduce

为了描述action是如何修改store里面的数据,我们需要编写reducers。reducers,它接收先前的state和action,并放回新的store,一个项目的项目往往处理action会特别多,这时候就需要拆分reduces

cosnt initFilter = all
function Filter(state=initFilter,action){
     switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
      return action.filter
    default:
      return state  }
}
function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    default:
      return state
  }
}import { combineReducers, createStore } from 'redux'
let reducer = combineReducers({ Filter, todos })let store = createStore(reducer)

react-redux

如果想在react中使用redux,需要借助react-redux库,这个库是将redux连接起来。它提供了一个组件和一个方法。

import{ Provider,connect} from 'react-redux'

provider

它是一个组件,需要一个store,这个store参数就是createStore创建出来的store。

<Provider store ={store}>
     <App/>
</Provider>

connect

App一般是根组件,如果某个组件想要使用store里面的数据。需要connect 这个方法,在class组件的使用。

class App extends React.Component{
render(){
        console.log(this.props.count)]
        console.log(this.props.onDipatchSetData)
       return <div>=-=</div>
  }
}
const mapStateToProps =(state) =>({
  count:state.count // 如果这里涉及计算,推荐使用reselect库,后续会讲到为什么需要这个库
})
const mapDispatchToProps =(dispatch) =>({
    onDispatchSetData: (count) => dispatch({type:'COUNT',payload:{count:10}}) 
})
export default Connect(mapStateToProps,mapDispatchToProps)(App)

reselect

如果mapStateToProps 中的涉及对数据的计算,避免不必要的重复计算,它可以对计算的数据进行缓存,如果store里面的某个数据没有改变,那么它不会重新计算。

import {createSelector,createStructuredSelector} from 'reselect'
state ={   obj:{    count:0
    }
}// 假设store里面的state的数据是这样

const selectObj = (state) => state.obj

const makeSelectCount = () => createSelector(selectObj,(state) => state.count)
const mapStateToProps =(state) =>({
  count:state.count 
})const mapStateToProps =createStructuredSelector({    count:makeSelectCount ()})

immer

reducers对数据进行更新,返回一个纯函数,返回值是一个不可变对象,关于reduce这一层还有库immutable-js。immer是 mobx 的作者写的一个 immutable 库,核心实现是利用 ES6 的 proxy,几乎以最小的成本实现了 js 的不可变数据结构,简单易用、体量小巧、设计巧妙,满足了我们对JS不可变数据结构的需求。

import {produce} from 'immer'
const initState = {
    count:0
}
const CountReducer = (state =initState,action ) =>
produce(state,(drafe)=>{
    switch(action.type){
    case "SET_COUNT":
        drafe.count = action.payload.count
    break
    }
})

saga

想处理一个异步的action,可以借助saga来完成。saga是一个用于管理Redux 应用异步操作的中间件。 redux-saga 通过创建 Sagas将所有的异步操作逻辑收集在一个地方集中处理。可以用来代替 redux-thunk 中间件。而且提供了takeLatest/takeEvery可以对事件的仅关注最近事件、关注每一次、事件限频。

import {call,all,put,takeLatest,takeEvery} from 'redux-saga/effects'
// 定义action 常量
const constants ={
    REQUEST_GET_DATA:"requestGetData",
    REQUEST_GET_DATA_SUCCESS:"requestGetDataSuccess",
    REQUEST_GET_DATA_FAILED:'requestGetDataFailed'
}
// 定义action
const requestGetData  =() =>({
    type:constants.REQUEST_GET_DATA,
    payload:{}
})
// 成功的action
const requestGetDataSuccess =(data)=>({
    type:constants.REQUEST_GET_DATA_SUCCESS,
    payload:{data}
})
// 失败的action
const requestGetDataFailed =() =>({
    type:constants.REQUEST_GET.DATA.FAILED,
    payload:{}
})
// 定义saga

function* getData(action){
if(action.type !== constants.REQUEST_GET_DATA) return 
    try{
        const {data} = yiled call(featch('/getData'))
          yiled put(requestGetDataSuccess(data)) // 提交成功的action后,在reduce中监听,在改变store里面数据
    }catch(error){
        yield put(requestGetDataFailed())    
    }
}

function * rootCountSaga{
    yield all([takeEvery(constants.REQUEST_GET_DATA,getData)])
}