Redux
是一款状态管理库,而且提供了react-redux
库来与React
亲密配合, 可是老是傻傻分不清楚这2者提供的API
和相应的关系。这篇文章就来理一理。react
Redux
的核心由三部分组成:Store
, Action
, Reducer
。redux
Store
: 是个对象,贯穿你整个应用的数据都应该存储在这里。Action
: 是个对象,必须包含type
这个属性,reducer
将根据这个属性值来对store
进行相应的处理。除此以外的属性,就是进行这个操做须要的数据。Reducer
: 是个函数。接受两个参数:要修改的数据(state) 和 action
对象。根据action.type
来决定采用的操做,对state
进行修改,最后返回新的state
。===== Store ===== { todos: [], visibilityFilter: 'SHOW_ALL' } ===== Action ===== { type: 'ADD_TODO', text: 'Build my first Redux app' } ===== Reducer ===== const todos = (state = [], action) => { switch (action.type) { case 'ADD_TODO': return [ ...state, { id: action.id, text: action.text, completed: false } ] default: return state } }
在上一部分,咱们提到了,咱们触发action
→ reducer来处理
。这就是两者之间的关系。那么咱们怎么触发action
呢?Store
这个对象提供了dispatch方法
→ 触发action
。dispatch
方法接受action
对象做为参数。所以,咱们能够了解三者之间的关系:app
`store` ➡️ `dispatch` ➡️ `action` ⬅️ `reducer`
咱们经过redux
提供的createStore
这个方法来建立一个Store
。它接受对store
进行处理的reducer
做为参数。ide
Store
有三个方法:函数
getState
:用来获取store
里面存储的数据。dispatch
: store
里的数据不能直接修改,只能经过触发action
来进行修改,这个方法就是用来触发action
。subscibe
:订阅store
改变时,要进行的操做。好比在react
中,当store
改变时,咱们须要调用render
方法对视图进行更新。const store = createStore(reducer); store.getState(); // { todos: [], visibilityFilter: 'SHOW_ALL' } store.dispatch({ type: 'ADD_TODO', text: 'Build my first Redux app' }); store.subscibe(() => { console.log(store.getState()); });
咱们能够将对store
的操做,写在一个reducer
中,好比:工具
function todoApp(state = initialState, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return Object.assign({}, state, { visibilityFilter: action.filter }) case ADD_TODO: case TOGGLE_TODO: return Object.assign({}, state, { todos: todos(state.todos, action) }) default: return state } }
能够看到这个reducer
对store
的visibilityFilter
和todos
的两部分数据进行了处理。随着应用的复杂,若是咱们把对全部数据的处理,都写在一个reducer
中,那么它会变得很冗杂。若是咱们将对每一部分的数据的处理,写在一个单独的reducer
中,它接受该部分的数据做为state
。那么整个reducer
会变得整洁和清晰。ui
所以,redux
为咱们提供了combineReducer
这个API
,帮助咱们分开书写reducer
, 而且最终把这些reducer
给集合到一个根reducer
中。spa
// 对todos进行处理 function todos(state = [], action) { switch (action.type) { case ADD_TODO: return [ ...state, { text: action.text, completed: false } ] default: return state } } // 对 visibilityFilter 进行处理 function visibilityFilter(state = SHOW_ALL, action) { switch (action.type) { case SET_VISIBILITY_FILTER: return action.filter default: return state } } // 生成 root reducer function todoApp(state = {}, action) { return { visibilityFilter: visibilityFilter(state.visibilityFilter, action), todos: todos(state.todos, action) } } // 建立store const store = createStore(todoApp)
上一部分咱们介绍了redux
的核心。能够看到,redux
是独立的应用状态管理工具。它是能够独立于react
以外的。若是咱们须要在react
当中运用它,那么咱们须要手动订阅store
的状态变化,来对咱们的react
组件进行更新。那么react-reudx
这个工具,就帮咱们实现了这个功能,咱们只需对store
进行处理,react
组件就会有相应的变化。code
这个工具主要提供两个API
:对象
connect
如今咱们有了store
,那么咱们怎么才能在咱们的组件中对它们进行操做呢?connect
就为提供了这个功能。它接受mapStateToProps
, mapDispatchToProps
等做为参数。好比在个人TodoList
这个组件中须要用到todos
这部分数据,那么我完善mapStateToProps
这个函数,它接受store
中的state
做为参数,返回一个对象,属性就是state
中咱们须要的数据:
const mapStateToProps = state => { return { todos: state.todos } }
mapStateToProps
就将咱们的state
转换为了props
对象。
一样的,咱们可能须要在组件中对state
进行处理。mapDispatchToProps
就是帮助咱们在组件中经过props
调用dispatch
来触发action
的:
const mapDispatchToProps = dispatch => { return { onTodoClick: id => { dispatch(toggleTodo(id)) } } }
最后咱们调用connect
这个方法,将mapStateToProps
, mapDispatchToProps
生成的props
注入到须要使用它的组`中:
const VisibleTodoList = connect( mapStateToProps, mapDispatchToProps )(TodoList)
这样,咱们在TodoList
这个组件中,就能直接经过props.todos
获取到todos
中的数据, 经过props.onTodoClick
对todos
进行处理。
provider
上面咱们调用connect
时,在mapStateToProps
和 mapDispatchToProps
咱们分别用到了store
的state
和dispatch
。可是在组件中的store
是哪里凭空冒出来的呢?
provider
就是来解决这个事的。Provider
使它的子孙在调用connect
方法时,都能获取到store
。
const VisibleTodoList = connect( mapStateToProps, mapDispatchToProps )(TodoList) const App = () => ( <div> <AddTodo /> <VisibleTodoList /> <Footer /> </div> ) <Provider store={store}> <App /> </Provider>
这样,Provider
的子孙组件都能在调用connect
时获取到store
。
Redux: store
, action
, reducer
store
: getState
, dispatch
, subscribe
combineReducers
createStore
store
➡️ dispatch
➡️ action
⬅️ reducer
react-redux:
connect
: 将store
做为props
注入Provider
: 使store
在子孙组件的connect
中可以获取到。