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中;
相关文章
相关标签/搜索