React-native項目中使用redux

準備工做

根據須要安裝如下組件。html

  • redux(必選)
  • react-redux(必選):redux做者爲方便在react上使用redux開發的一個用戶react上的redux庫;
  • redux-devtools(可選):Redux開發者工具支持熱加載、action 重放、自定義UI等功能;
  • redux-thunk:實現action異步的middleware;
  • redux-persist(可選):支持store本地持久化;
  • redux-observable(可選):實現可取消的action;
npm install --save redux
npm install --save react-redux
npm install --save-dev redux-devtools

react-redux介紹

react-redux是Redux 官方提供的 React 綁定庫。 具備高效且靈活的特性。react

視圖層綁定引入了幾個概念:

  • <Provider> 組件: 這個組件須要包裹在整個組件樹的最外層。這個組件讓根組件的全部子孫組件可以輕鬆的使用 connect() 方法綁定 store。
  • connect():這是 react-redux 提供的一個方法。若是一個組件想要響應狀態的變化,就把本身做爲參數傳給 connect() 的結果,connect() 方法會處理與 store 綁定的細節,並經過 selector 肯定該綁定 store 中哪一部分的數據。
  • selector:這是你本身編寫的一個函數。這個函數聲明瞭你的組件須要整個 store 中的哪一部分數據做爲本身的 props。
  • dispatch:每當你想要改變應用中的狀態時,你就要 dispatch 一個 action,這也是惟一改變狀態的方法。

react-redux提供如下API:git

  • Provider
  • connect

Provider

API原型:<Provider store>github

使組件層級中的 connect() 方法都可以得到 Redux store(將store傳遞給App框架)。一般狀況下咱們須要將根組件嵌套在 標籤 中才能使用 connect() 方法。npm

class Index extends Component {
    render() {
        return  <Provider store={configureStore()}>
            <AppWithNavigationState />
        </Provider>     }
}

以上代碼片斷的完整部分能夠在課程源碼中查找。redux

在上述代碼中咱們用 標籤包裹了根組件AppWithNavigationState,而後爲它設置了store參數,store (Redux Store)接受的是應用程序中惟一的 Redux store 對象。框架

connect

API原型:connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])異步

鏈接 React 組件與 Redux store,鏈接操做會返回一個新的與 Redux store 鏈接的組件類,而且鏈接操做不會改變原來的組件類。ide

react-redux`提供了connect函數,connect是一個高階函數,首先傳入mapStateToProps、mapDispatchToProps,而後返回一個生產 Component 的函數(wrapWithConnect),而後再將真正的Component做爲參數傳入wrapWithConnect(MyComponent),這樣就生產出一個通過包裹的Connect組件,如:`export default connect(mapStateToProps)(HomePage);

使用步驟

  • 建立action函數

    /* * action 類型 */
    	
      export const ADD_TODO = 'ADD_TODO';
      export const COMPLETE_TODO = 'COMPLETE_TODO';
      export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'
    	
      /* * 其它的常量 */
    	
      export const VisibilityFilters = {
          SHOW_ALL: 'SHOW_ALL',
          SHOW_COMPLETED: 'SHOW_COMPLETED',
          SHOW_ACTIVE: 'SHOW_ACTIVE'
      };
    	
      /* * action 建立函數 */
    	
      export function addTodo(text) {
          return { type: ADD_TODO, text }
      }
    	
      export function completeTodo(index) {
          return { type: COMPLETE_TODO, index }
      }
    	
      export function setVisibilityFilter(filter) {
          return { type: SET_VISIBILITY_FILTER, filter }
      }

    以上代碼片斷的完整部分能夠在課程源碼中查找。

  • 建立reducer

    import { combineReducers } from 'redux'
      import { ADD_TODO, COMPLETE_TODO, SET_VISIBILITY_FILTER, VisibilityFilters } from './actions'
      const { SHOW_ALL } = VisibilityFilters
    	
      function visibilityFilter(state = SHOW_ALL, 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
                      }
                  ]
              case COMPLETE_TODO:
                  return [
                      ...state.slice(0, action.index),
                      Object.assign({}, state[action.index], {
                          completed: true
                      }),
                      ...state.slice(action.index + 1)
                  ]
              default:
                  return state
          }
      }
      //經過combineReducers將多個reducer合併成一個rootReducer
      const todoApp = combineReducers({
          visibilityFilter,
          todos
      })
    	
      export default todoApp

    以上代碼片斷的完整部分能夠在課程源碼中查找。

這裏經過Redux提供的combineReducers方法,將多個reducer聚合成一個rootReducer。

  • 建立store

    import {createStore} from 'redux'
      import todoApp from './reducers'
    	
      let store = createStore(todoApp)

    這裏經過Redux提供的createStore方法,建立了store;

  • 使用<Provider>包裹根組件

    import {Provider} from 'react-redux'
      export default class index extends Component {
          render() {
              return (<Provider store={store}>
                  <App/>
              </Provider>)       }
      }

    以上代碼片斷的完整部分能夠在課程源碼中查找。

這裏咱們使用react-redux提供的<Provider>來包裹咱們的根組件,讓根組件的因此子組件都能使用 connect() 方法綁定 store。

  • 包裝 component:

    function selectTodos(todos, filter) {
          switch (filter) {
              case VisibilityFilters.SHOW_ALL:
                  return todos
              case VisibilityFilters.SHOW_COMPLETED:
                  return todos.filter(todo => todo.completed)
              case VisibilityFilters.SHOW_ACTIVE:
                  return todos.filter(todo => !todo.completed)
          }
      }
    	
      // Which props do we want to inject, given the global state?
      // Note: use https://github.com/faassen/reselect for better performance.
      function select(state) {
          return {
              visibleTodos: selectTodos(state.todos, state.visibilityFilter),
              visibilityFilter: state.visibilityFilter
          }
      }
    	
      // 包裝 component ,注入 dispatch 和 state 到其默認的 connect(select)(App) 中;
      export default connect(select)(App)

    以上代碼片斷的完整部分能夠在課程源碼中查找。

經過上述代碼咱們聲明App組件須要整個 store 中的哪一部分數據做爲本身的 props,這裏用到了connect,咱們將select做爲參數傳給connectconnect會返回一個生成組件函數,而後咱們將App組件當作參數傳給這個函數。

connect是一個高階函數,首先傳入mapStateToProps、mapDispatchToProps,而後返回一個生產 Component 的函數(wrapWithConnect),而後再將真正的Component做爲參數傳入wrapWithConnect(MyComponent),這樣就生產出一個通過包裹的Connect組件

  • 發送(dispatch)action

    render() {
          // Injected by connect() call:
          const {dispatch, visibleTodos, visibilityFilter} = this.props
          return (
              <View>
                  <AddTodo
                      onAddClick={text =>
                          dispatch(addTodo(text))
                      }
                      toast={this.toast}
                  />               <TabBar
                      filter={visibilityFilter}
                      onFilterChange={nextFilter =>
                          dispatch(setVisibilityFilter(nextFilter))
                      }/>               <TodoList
                      todos={visibleTodos}
                      onTodoClick={index =>
                          dispatch(completeTodo(index))
                      }
                      toast={this._toast()}
                  />               <Toast ref={toast => this.toast = toast}/>           </View>       )
      }

    以上代碼片斷的完整部分能夠在課程源碼中查找。

在這裏咱們經過dispatch將action發送到store,store會將這個action分發給reducerreducer會建立當前state的副本,而後修改該副本並返回一個新的state,這樣一來store樹將被更新,而後對應組件的props將被更新,從而組件被更新;

總結

  • Redux 應用只有一個單一的 store。當須要拆分數據處理邏輯時,你應該使用 reducer 組合 而不是建立多個 store;
  • redux一個特色是:狀態共享,全部的狀態都放在一個store中,任何component均可以訂閱store中的數據;
  • 並非全部的state都適合放在store中,這樣會讓store變得很是龐大,如某個狀態只被一個組件使用,不存在狀態共享,能夠不放在store中;
相關文章
相關標籤/搜索