Redux Basic Concepts

Actions

action是将数据从应用传递到store的介质,是store的唯一信息来源,使用store.dispatch()将信息发送到store中。

actions是纯JavaScript对象。actions必须有一个type属性来标明正在执行的action的类型,type属性通常被定义为字符串常量。

Action Creators

定义action的函数,函数一般返回一个action。如果想要发起一个dispatch,需要将action createor的结果传入dispatch作为参数。例如一个todo应用中:

// action creator
function addTodo(text) {
    return {
        type: ADD_TODO,
        text
    }
}

// dispatch
dispatch(addTodo(text))

或者绑定在一个函数上,使用时就直接调用绑定的函数:

const boundAddTodo = text => dispatch(addTodo(text))
boundAddTodo(text)

Reducers

指定程序的state怎么根据action来进行响应。

在redux中,应用程序的所有state都存储为一个单独的对象,reducer可以确定这个对象的存储形态。

处理actions

reducer是一个纯函数,它接收先前的state和一个action作为参数,并返回新的state

(previousState, action) => newState

之所以称为reducer是因为它其实调用了Array.proptotype.reduce(reducer, ?initialValue)。reducer必须是纯函数,表示绝对不能再reducer中做如下事情:

  • 对参数进行变形
  • API调用或路由变形等副作用
  • 调用非纯函数,例如Date.now()或者Math.random()

给予reducer相同的参数,它应该计算出相同的结果并且返回这个结果,没有副作用,没有API的调用,没有变形,仅仅是一个计算。

function todoApp(state = initialState, action) {
    switch (action.type) {
        case 'SET_VISIBILITY_FILTER':   
            return Object.assign({}, state, {
                visibilityFilter: action.filter
            })
        default: 
            return state
    }
}
  • 这里使用了Object.assign()复制对象来避免state被改变,如果使用Object.assign(state, {visibilityFilter: action.filter}}也是错误的:第一个参数会被改变。所以必须提供一个空对象作为第一个参数。也可以用ES6的解构复制,像这样:{...state, {visibilityFilter: action.filter}}

  • 需要有一个default时要返回的情况,因为可能会有别的不确定的action,所以这里默认返回了原来的state

两个reducer可以通过combineReducers()结合:

const todoApp = combineReducers({
    visibilityFilter,
    todos
})

Store

store的用途:

  • 存储应用程序的state
  • 通过getState()来获取state
  • 通过dispatch(action)来更新state
  • 通过subscribe(listener)注册监听者
  • 通过subscribe(listener)返回的函数来注销监听者 要注意的是一个应用程序中最好只有一个store。当想要拆分数据逻辑时,可以用reducer composition而不是创建很多store
    let store = createStore(todoApp)
    
    createStore()可以有第二个参数,作为state的初始值传入。

Data Flow

redux遵循严格的单向数据流(strict undirectional data flow)

意味着一个应用程序中所有的数据遵循相同的生命周期模式,使程序逻辑更加可预测并且易于理解。也支持数据规范化,这样就不会存在多个相同数据的副本。

redux的数据生命周期遵循以下4步:、

  • 调用store.dispatch(action)来派发action
  • store调用定义好的reducer来响应action
  • reducer会组合多个reducer的输出形成单个状态树
  • store会接收reducer返回的状态树并存储起来

与React结合

首先是展示组件和容器组件的区别:

展示组件 容器组件
作用 决定组件的外观 决定组件的作用(数据获取,状态更新)
与redux的联系
如何获取数据 props传入 通过监听redux的state
如何改变数据 调用props的回调 dispatch action

大部分组件应该都是展示组件,但是也需要容器组件来将组件和redux的store联系起来。但是并不意味着容器组件应该在组件树顶部。

connect()提供了很多有用的优化来防止不必要的重复渲染,(其中的一点就是不必去定制shouldComponentUpdate方法)

mapStateToProps:决定了怎么将当前的redux store转换为想包裹的展示组件的props mapDispatchToProps:可以接收dispatch()方法并且要注册到展示组件想要注册的回调

别忘了最外围还有一个<Provider></Provider>组件传递store

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

results matching ""

    No results matching ""