Redux basic tutorial

@(blog)

Redux basic tutorial

本文的读者为相识flux观点,熟习react,相识es6语法的同砚

redux 是近来很火的一个 flux 框架,短短的一个月如今已经有2900+的 star 了,watch以后天天收到几百封 pr 的邮件,空话就不多说了。
为何要用 redux ,请看衔接 The Evolution of Flux Frameworks

主要特性

  • Everything (Stores, Action Creators, configuration) is hot reloadable. —— 配合起 hotloader 应当迥殊爽,虽然如今用的是 browserify,优点以为并不显著。
  • store 中的数据不受限定,可所以 number object array 等等,空话,由于它的 store 只是简朴的函数。
  • 供应 devtools ,监控 action 的触发以及 state 的变化。
  • 源码清楚简朴,轻量级,基础不须要文档,直接看源码就好了….瑕玷就是假如看不懂源码,光看文档会以为不够清楚。
  • api 很精简,不必记茫茫多的 api
  • every thing is simple function
  • connecterprovider 这两个东西用起来总以为很烦琐,不那么文雅。

下面经由历程写的一个简朴counter的例子 引见 redux 的中心要领以及一些须要注重的处所。

  • 同步与异步两种actionCreator
  • middleware的运用
  • dispatch actions
  • 拿到并同步state

代码放在https://github.com/yeatszhang/redux-tutorial, 须要装置gulp

代码是基于分支 v1.0.0-rc api稍微有些区分,概况见 Breaking API changes for 1.0

actionCreator

actions creator 是用来天生 action 的函数,在默许情况下能够吸收返回object或许function 的函数,很多人进修flux的时刻把action与actionCreator弄殽杂….:

// 直接返回object
actionCreators.addTodo = function(text) {
  return {
    type: types.ADD_TODO,
    text
  };
}

// 返回函数
actionCreators.incrementAsync = function() {
  return (dispatch, getState) => {
    // actionCreator中能够经由历程getState取得当前的state
    console.log(getState());
    // 异步action
    setTimeout(() => {
      dispatch({
        type: INCREMENT_COUNTER2,
      });
    }, 1000);
  };
};

在没有运用任何 middleware 的情况下,只要这有两种 action 能够被 dispatch

app

在动态内容的最外层应当运用Provider举行包裹,provider吸收store作为参数,注重children是一个函数并非reactElement
provider将store作为context往子节点举行通报,并完成store的热替代。因此在provider内的组件实在能够不经由历程connect来拿到dispatch以及state,而直接经由历程context拿到store对象,不过作者不引荐这么做。

import React from 'react';
import { createStore, applyMiddleware, combineReducers } from 'redux';
// redux midlleware repositories
import thunk from 'redux-thunk';
// 将 redux 与 react 相干的部份,如 connector provider 零丁抽取出来
import { Provider } from 'react-redux';
import reducers from '../reducers';
import CounterApp from './CounterApp.js';
import logMiddleware from '../middleWares/logMiddleware.js';

const reducer = combineReducers(reducers);
const createStoreWithMiddleware = applyMiddleware(thunk, logMiddleware)(createStore);
const store = createStoreWithMiddleware(reducer);
// 运用middleWare thunk, 假如没有自定义中间层的需求能够直接写
// const store = createStore(reducer);

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        {() => <CounterApp />}
      </Provider>
    );
  }
}

smart component

smart component具有两个特性:

  1. 自动关联store中的state并自动re-render
  2. 能够经由历程dispatch来分发事宜,从而触发store的更新

刚打仗redux的同砚肯定会以为这个connect很难以明白。照样在代码内里说把。。。

/**
 * Created by yichizhang on 15/7/26.
 */

import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { Connector } from 'react-redux';
import Counter from '../components/Counter';
import actionCreators1 from '../actionCreators/actionCreators1.js';
import actionCreators2 from '../actionCreators/actionCreators2.js';

// state 是各reducer中state的鸠合
function select(state) {
  // 从各reducer中挑选出component须要监听的state
  return {
    counter1: state.reducer1.counter,
    counter2: state.reducer2.counter,
  };
}

export default class CounterApp extends Component {
  // select函数的返回值会与dispatch组装程一个object作为参数
  // 从这里看出connector就是帮助拿到provider中store的dispatch要领以及挑选出须要运用的state
  renderChild({ counter1, counter2, dispatch}) {
    // 个人以为如许运用action非常不方便,尤其是当组件只须要触发actions不须要监听store的变化的时刻。我会偷懒经由历程context去拿到dispatch~~
    const actions1 = bindActionCreators(actionCreators1, dispatch);
    const actions2 = bindActionCreators(actionCreators2, dispatch);
    const props = { ...actions1, ...actions2, counter1, counter2 };
    // 一切的action以及state都邑以props的情势供应给Counter,然后在Counter内里就能够随心所欲了~
    return <Counter {...props} />;
  }

  render() {
    return (
      <Connector select={select}>
        {this.renderChild}
      </Connector>
    );
  }
}

reducer

redux以为程序员不须要去写store中的逻辑而只须要写明对state的处置惩罚逻辑就好:

old  sate => action  => new state

这是一个完整同步的历程。reducer只须要声明初始状况以及state在吸收到action以后的转变划定规矩就能够了。

import React from 'react/addons';
import {INCREMENT_COUNTER1, DECREMENT_COUNTER1} from '../constants/actionsTypes.js';
const update = React.addons.update;

// state可所以任何范例
const initialState = {
  counter: 0,
};

// reducer只是一个简朴的switch要领
export default function counter(state = initialState, action = null) {
  switch (action.type) {
    case INCREMENT_COUNTER1:
      // 须要注重的是connector当select中的state发生变化时会做一个shallow equal的操纵,
      // 所以假如须要操纵援用值的时刻肯定不能直接赋值,须要运用addon中的update或许immutable.js,晓得看到这两个东西又不想继承学了..实在很简朴
      // 如许能够大大防止反复的render,从而进步机能
      return update(state, {
        counter: {
          $set: state.counter + 1,
        },
      });
    case DECREMENT_COUNTER1:
      return update(state, {
        counter: {
          $set: state.counter - 1,
        },
      });
    default:
      return state;
  }
}

middleWare

感兴趣的同砚能够看看,一般来说默许的thunk就够用了。我在例子里加了个log的中间层

// 打印触发的action
function logMiddleware() {
  // 这里的next是下一个middleWare
  return function(next) {
    return function(action) {
      // 打印此action并运用下一个middleWare处置惩罚该action
      console.log(action);
      next(action);
    };
  };
}

export default logMiddleware;

// 下面是默许的thunk middleWare

function thunkMiddleware(_ref) {
  var dispatch = _ref.dispatch;
  var getState = _ref.getState;

  return function (next) {
    return function (action) {
      // 假如是函数则将dispatch与getState作为参数实行函数,不然交给写一个middleware处置惩罚
      return typeof action === 'function' ? action(dispatch, getState) : next(action);
    };
  };
}

结语

实在redux不明白的处所直接看源码更好,redux的代码量很小而且构造也很清楚,发起人人都去看,不过作者貌似函数式编程的头脑很重,大批运用润饰器的语法,另有reduce~ 挺绕的~

以后会总结本身浏览redux源码的一些心得,以及各功能模块的完成道理~

    原文作者:YeatsZhang
    原文地址: https://segmentfault.com/a/1190000003033033
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞