Skip to content

wangning0/redux_demo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Redux 学习之旅

Redux三大原则

  • 单一的数据源

    整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。一般来说,你会通过store.dispatch()将action传到store,并且每个action必须是javascript对象

  • State是只读的

    惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

  • 使用纯函数来执行修改

Action

  • 一般来说,你会通过store.dispatch()将action传到store,并且每个action必须是javascript对象

  • 事实上,创建action对象很少用这种每次直接声明对象的方式,更多的是通过一个创建函数,这个函数被称为Action Creator

      function addTodo(text) {
          return {
          type: ADD_TODO,
          text
          };
      }
    

Reducer

  • Redux中的reducer是一个纯函数,传入state和action,返回一个新的state tree,简单而纯粹的完成某一件具体的事情,没有依赖,简单而纯粹是它的标签。

      const counter = (state=0,action)=>{
           switch (action.type) {
            case 'INCREMENT':
              return state + 1;
            case 'DECREMENT':
              return state - 1;
            default:
              return state;
        }
      }
    
  • 永远不要在reducer里面做这些操作

    • 修改传入参数
    • 执行有副作用的操作,如api请求和路由跳转
    • 调用非纯函数 Date.now() Math.random()

Store

store是用来维持应用所有的state树的一个对象。改变store内state唯一的途径是对她dispatcher一个action

Store是一个具有一下四个方法的对象:

  • getState()

    返回应用当前的state树

  • dispatch(action)

分发action,触发state变化的唯一途径,会使用当前getState()的结果和传入的action以同步方式的调用store的reduce函数,返回值被作为下一个state。从现在开始,这就成为了getState的返回值,同时变化监听器会触发。

  • subscribe(listener)

添加一个变化监听器,每当dispatch action的时候就会执行,state树中的一部分可能已经变化,这是一个底层api,多数情况下,不会直接使用它,会使用一些react的绑定

  • replaceReducer(nextReducer)

Redux 的顶层api介绍

  • createStroe

    • 调用方式:createStrore(reducer,[initialState])
  • combineReducers

    • 调用方式:comebineReducers(reducers)

              combineReducers({todos,counter});
              
              import {combineReducers} from 'redux';
              import * as reducers from './reducers';
              const todoApp = combineReducers(reducers);
      
  • applyMiddleware

    • 调用方式:applyMiddleware(...middlewares)
  • bindActionCreators

    • 调用方式:bindActionCreators(actionCreators, dispatch)

        let actions = {
            addItem:(text)=>{
                type:type.ADD_ITEM,
                text
            }
        }
        bindActionCreators(actions,dispatch)
        //等价于=>
        /*
        return {
            addItem:(text)=>dispatch({type:type.ADD_ITEM,text})
        }
        */
      
  • compose

    • 调用方式:compose(...functions)
    • compose 用来实现从右到左来组合传入的多个函数,它做的只是让你不使用深度右括号的情况下来写深度嵌套的函数,仅此而已。

React-redux

  • 提供connectProvider

  • Provider 这个模块作为整个App的容器,在原有的App Container的基础上再包上一层,它的工作很简单,接受Redux的store作为props,可以通过this.context.store访问到。

  • 这个模块算是真正意义上连接了redux 和 react,connect就是酱store中的必要数据作为props传递给React组件来render,并包装action creator用于在响应数据操作时dispatcher一个action

  • connect([mapStateToProps],[mapDispatchToProps],[mergeProps],[options])

    • mapStateToProps是一个函数,返回值表示的是需要merge进props的state。默认值为()=>({})什么都不传。(state,props)=>({})

    • mapDispatchToProps是可以是一个函数,返回值表示的是需要merge进props的actionCreators这里的actionCreator应该是已经包装了dispath了的,推荐使用redux的bindActionCreators函数

               (dispatch, props) => ({ // 通常会省略第二个参数
                 ...bindActionCreators({
                   ...ResourceActions
                 }, dispatch)
                })
        
                //demo
                import * as actionCreators from './actionCreators'
                import { bindActionCreators } from 'redux'
                
                function mapStateToProps(state) {
                  return { todos: state.todos }
                }
                
                function mapDispatchToProps(dispatch) {
                  return { actions: bindActionCreators(actionCreators, dispatch) }
                }
                
                export default connect(mapStateToProps, mapDispatchToProps)(Component)
      

超酷的开发工具Redux-devtools

npm install --save-dev redux-devtools redux-devtools-log-monitor redux-devtools-dock-monitor

  • redux-devtools:redux的开发工具包,而且DevTools支持自定义的 monitor 组件,所以我们可以完全自定义一个我们想要的 monitor 组件的UI展示风格,以下两个是我们示例中用到的。

  • redux-devtools-log-monitor: 这是Redux Devtools 默认的 monitor ,它可以展示state 和 action 的一系列信息,而且我们还可以在monitor改变它们的值。

  • redux-devtools-dock-monitor:这monitor支持键盘的快捷键来轻松的改变tree view在浏览器中的展示位置,比如不断的按‘ctrl + q’组合键可以让展示工具停靠在浏览器的上下左右不同的位置,按“ctrl+h”组合键则可以控制展示工具在浏览器的显示或隐藏的状态。

      import React from 'react';
      import { createDevTools } from 'redux-devtools';
      import LogMonitor from 'redux-devtools-log-monitor';
      import DockMonitor from 'redux-devtools-dock-monitor';
      
      export default createDevTools(
        <DockMonitor toggleVisibilityKey='ctrl-h'
                     changePositionKey='ctrl-q'>
          <LogMonitor />
        </DockMonitor>
      );
      
      //
      import React from 'react'
      import { render } from 'react-dom'
      import { Provider } from 'react-redux'
      import App from './containers/App'
      import DevTools from './containers/DevTools'
      import { createStore, compose } from 'redux';
      import todoApp from './reducers'
      
      // 把多个 store 增强器从右到左来组合起来,依次执行
      // 这个地方完全可以不用compose,演示一下compose的使用
      const enhancer = compose(
        DevTools.instrument()
      );
      
      let store = createStore(todoApp, enhancer)
      let rootElement = document.getElementById('app')
      
      render(
        <Provider store={store}>
          <div>
            <App />
            <DevTools />
          </div>
        </Provider>,
        rootElement
      )
    

理解和使用Middleware

Redux中的middleware就是接受不同类型的action对象作为输入,负责改变store中的dispatch方法,从而达到我们预期的需求。它提供的是位于action被发起之后,到达reducer之前的扩展点

我们可以利用 Redux middleware 来进行日志记录、创建崩溃报告、调用异步接口或者路由等等。

可以使用redux的applyMiddleware方法将middlewares串起来,并返回一个增强型的 createStore 。

compose 将从右到左来传入的多个函数组合起来

开发建议

开发复杂的应用时,不可避免的会有一些数据相互引用,建议尽可能的把state范式化,不存在嵌套。把所有数据放到一个对象里,每个数据以id为主键,不同数据相互应用时通过id来查找,把应用的state想象成数据库。normalizr文档有详细阐述,例如在实际开发中,在state里同时存放todosById:{id->todo}todos:array<id>是比较好的方式。

很多时候,我们经常要先把前面和后面都切开,可以选择帮助类 React.addons.update updeep Immutable 时刻谨记永远不要在克隆state前修改它

尽可能将嵌套的API响应范式化

    {
      selectedsubreddit: 'frontend',
      postsBySubreddit: {
        frontend: {
          isFetching: true,
          didInvalidate: false,
          items: []
        },
        reactjs: {
          isFetching: false,
          didInvalidate: false,
          lastUpdated: 1439478405547,
          items: [
            {
              id: 42,
              title: 'Confusion about Flux and Relay'
            },
            {
              id: 500,
              title: 'Creating a Simple Application Using React JS and Flux Architecture'
            }
          ]
        }
      }
    }
    
    //===>转化为
    
    {
      selectedsubreddit: 'frontend',
      entities: {
        users: {
          2: {
            id: 2,
            name: 'Andrew'
          }
        },
        posts: {
          42: {
            id: 42,
            title: 'Confusion about Flux and Relay',
            author: 2
          },
          100: {
            id: 100,
            title: 'Creating a Simple Application Using React JS and Flux Architecture',
            author: 2
          }
        }
      },
      postsBySubreddit: {
        frontend: {
          isFetching: true,
          didInvalidate: false,
          items: []
        },
        reactjs: {
          isFetching: false,
          didInvalidate: false,
          lastUpdated: 1439478405547,
          items: [ 42, 100 ]
        }
      }
    }

理解Middleware

[Middleware](https://github.com/wangning0/redux_demo/blob/master/middleware.js)

长用的react插件

  • redux-thunk
  • redux-promise
  • redux-actions

异步Action

当调用异步API时,有两个非常关键的时刻:发起请求的时刻,和接收到响应的时刻(也可能时超时)。每个API请求都至少需要dispatch三个不同的action

  • 一个通知reducer请求开始的action
  • 一个通知reducer请求成功结束的action
  • 一个通知reducer请求失败的action

可是设置不同的字段来作为标记位

异步Action Creator

把定义的同步action creator 和网络请求结合起来呢?标准的做法是使用redux thunkmiddleware. 通过使用指定的 middleware,action creator 除了返回action对象外还可以返回函数,这个函数可以执行异步api请求,还可以dispatch action.就像dispatch前面定义的同步action一样

用于生成action creator 的函数

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published