Pre-release

@gaearon gaearon released this Jun 9, 2015 · 2625 commits to master since this release

Assets 2

Internal Refactoring & Custom Dispatchers

This release brings breaking changes necessary to start experimenting with middleware and extensibility (#6, #55). It does not bring any support for middleware per se, but it untangles “Dispatcher” (a function that tells how actions turn into state updates) from “Redux” (an instance holding the current state and managing subscriptions). It is now possible to specify your own Dispatcher if you want to experiment with ideas like middleware, time travel, action creators returning Promises or Observables, etc.

  • createDispatcher now returns a function you need to give to createRedux
  • createRedux is the primary API you'll use for initialization
  • Instead of dispatcher prop, a dispatch function prop is injected by the <Connector> and @connect
  • Instead of dispatcher prop, <Provider> and @provide accept a redux prop
  • Instead of dispatcher.getAtom(), use redux.getState()
  • Instead of dispatcher.setAtom(), you may pass a second initialState argument to createRedux
  • Instead of dispatcher.perfrorm() or dispatcher.dispatch(), use redux.dispatch()
  • bindActions is renamed to bindActionCreators and accepts dispatch as the second parameter
  • You may skip composeStores and createDispatcher completely and just use createRedux(stores) as a shortcut

How It Looks Like Now

Initialization

Short Way

This is a shortcut for the most common use case.

import { createRedux, Provider } from 'redux';
import * as stores from '../stores/index';

const redux = createRedux(stores);

export default class App {
  render() {
    return (
      <Provider redux={redux}>
        {() =>
          <CounterApp />
        }
      </Provider>
    );
  }
}
Long Way

This way of writing lets you use compose Stores differently, or even pass a custom Dispatcher function. Its signature is (initialState, setState) => (action) => ().

import { createRedux, createDispatcher, composeStores } from 'redux';
import * as stores from '../stores/index';

// Compose all your Stores into a single Store function with `composeStores`:
const store = composeStores(stores);

// Create a default Dispatcher function for your composite Store:
const dispatcher = createDispatcher(store); // You may use your custom function here

// Create a Redux instance using the dispatcher function:
const redux = createRedux(dispatcher);

export default class App {
  render() {
    return (
      <Provider redux={redux}>
        {() =>
          <CounterApp />
        }
      </Provider>
    );
  }
}

Hydration and dehydration

// server
const redux = createRedux(stores);
redux.dispatch(MyActionCreators.doSomething()); // fire action creators to fill the state
const state = redux.getState(); // somehow pass this state to the client

// client
const initialState = window.STATE_FROM_SERVER;
const redux = createRedux(stores, initialState);

Binding actions

import React from 'react';
import { connect, bindActionCreators } from 'redux';
import Counter from '../components/Counter';
import * as CounterActions from '../actions/CounterActions';

@connect(state => ({
  counter: state.counter
}))
export default class CounterApp {
  render() {
    const { counter, dispatch } = this.props;
    return (
      <Counter counter={counter}
               {...bindActionCreators(CounterActions, dispatch)} />
    );
  }
}