All notable changes to this project will be documented in this file. This project adheres to Semantic Versioning.
1.0.1 - 2015/08/15
- Fixes “process is not defined” on React Native (#525, #526)
- Removes dependencies on
invariant
andwarning
(#528) - Fixes TodoMVC example (#524, #529)
1.0.0 - 2015/08/14
- If
dispatch
is attempted while reducer is executing, an error is thrown. Note that you can dispatch from lifecycle hooks just fine. It's only reducers that are not allowed to dispatch. (reduxjs#368)
We moved under rackt Github org. This won't affect you, but the new official URL is https://github.com/rackt/redux. We did this because we share values, and we want to collaborate on creating better tools, libraries, documentation, and examples. Redux stays independent of React, but we will work closely with React Router community to figure out a better integration.
We have real docs now. There are a few missing pieces, but it's a terrific effort, so thanks to everybody who contributed in the past month to get this shipped. Thanks to Gitbook for providing great tooling, too.
There's been no shortage of great examples in Awesome Redux, but we're shipping two new built-in examples in 1.0. One of them is a very simple async application. Creating it is covered in async tutorial. Another example we ship is a “real-world” example. It's a port of somewhat well-known flux-react-router-example to Redux, and shows advanced techniques such as caching, data normalization, custom API middleware, and pagination. Hopefully this example will help answer some commonly asked questions.
- Unsubscribing during a dispatch is now fixed: reduxjs#462
bindActionCreators
now can also accept a function as the first argument: reduxjs#352- Dispatching from iframe now works: reduxjs#304
- Symbols can be used as action types: reduxjs#295 (Note: we don't recommend you to do this, because they're not serializable, so you can't record/replay user sessions.)
1.0.0-rc - 2015/07/13
- React-specific code has been moved to react-redux and will be versioned separately
createStore
no longer implicitly combines reducers- All middleware is now “smart” middleware
createStore
no longer accepts middleware- The thunk middleware is no longer included by default
combineReducers
now throws if you returnundefined
statecombineReducers
throws if you have nodefault
case- (React) Components now update correctly in response to the actions fired in
componentDidMount
- Dispatch from the middleware sends the dispatch through the whole middleware chain
Read the detailed upgrade notes on the release page.
1.0.0-alpha - 2015/06/30
- “Stateless Stores” are now called reducers. (reduxjs#137 (comment))
- The “Redux instance” is now called “The Store”. (reduxjs#137 (comment))
- The dispatcher is removed completely. (reduxjs#166 (comment))
is nowcomposeStores
composeReducers
.is gone.createDispatcher
is nowcreateRedux
createStore
.<Provider>
now acceptsstore
prop instead of.redux
- The new
createStore
signature iscreateStore(reducer: Function | Object, initialState: any, middlewares: Array | ({ getState, dispatch }) => Array)
. - If the first argument to
createStore
is an object,composeReducers
is automatically applied to it. - The “smart” middleware signature changed. It now accepts an object instead of a single
getState
function. Thedispatch
function lets you “recurse” the middleware chain and is useful for async: #113 (comment).
- The
dispatch
provided by the default thunk middleware now walks the whole middleware chain. - It is enforced now that raw Actions at the end of the middleware chain have to be plain objects.
- Nested dispatches are now handled gracefully. (#110, #119)
- The object in React context is renamed from
toredux
store
. - Some tests are rewritten for clarity, focus and edge cases.
- Redux in examples is now aliased to the source code for easier work on master.
Read the detailed upgrade notes on the release page.
0.12.0 - 2015/06/19
No breaking changes this time.
- Classes returned by decorators now expose a static
DecoratedComponent
property for easier testing - Dependencies on
lodash
andbabel-runtime
are dropped - Now compatible with Babel loose mode
composeStore
now ignores non-function values (useful in Babel loose mode)- A UMD build is added
- The initial action dispatched to the stores now has a built-in
@@INIT
type (might be useful to devtools)
0.11.1 - 2015/06/16
- Bugfix: when
Connector
select
property changes, the state did not recalculate (#107)
0.11.0 - 2015/06/14
- Renames
compose
root export tocomposeMiddleware
to clarify the intent - Fixes a bug with
getState
returning stale state after a hot reload (#90)
0.10.1 - 2015/06/13
Missing from the 0.10 release notes: React Native is now supported! (And that's actually a breaking change.)
Now, to import React-specific parts (containers or decorators), you need to either import from redux/react
or redux/react-native
:
// Import utilities and functions from redux
import { createRedux, bindActionCreators } from 'redux';
// Import components and decorators from redux/react
import { provide, Connector } from 'redux/react';
// React Native: Import components and decorators from redux/react-native
import { provide, Connector } from 'redux/react-native';
0.10 release also had a problem with ES6 code inside redux/react
and redux/react-native
entry points, which is now fixed. Please upgrade if you had problems with 0.10.
Changes introduced in 0.10.1:
Connector
now throws ifselect
returns something other than a plain object (reduxjs#85)- The custom dispatcher API is tweaked so
setState
now returns the state that was actually set. This makes custom dispatchers more composable. (reduxjs#77)
Happy reducing!
0.10.0 - 2015/06/13
Redux 1.0 is within striking distance! Can you believe how quickly Redux has matured? @rackt made the first commit only 14 days ago.
The 0.10 release is a follow-up to 0.9, with a focus on what we're calling (at least for now) middleware.
You can read all about middleware here. We plan to release some official middleware soon, but of course we'd also love to see middleware created by the community.
Just a small one: Redux includes a feature that enables you to return a function from an action creator to perform asynchronous dispatches. The function receives a callback and getState()
as parameters. This has behavior has been re-implemented as middleware and moved into a separate module called thunkMiddleware()
. It is included automatically when using the createRedux(stores)
shortcut, but not when using createDispatcher()
.
We have tests! Still need to improve coverage in a few areas, but we're currently at ~93%. Not bad! Big thanks to @emmenko for setting these up.
0.9.0 - 2015/06/09
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 tocreateRedux
createRedux
is the primary API you'll use for initialization- Instead of
dispatcher
prop, adispatch
function prop is injected by the<Connector>
and@connect
- Instead of
dispatcher
prop,<Provider>
and@provide
accept aredux
prop - Instead of
dispatcher.getAtom()
, useredux.getState()
- Instead of
dispatcher.setAtom()
, you may pass a secondinitialState
argument tocreateRedux
- Instead of
dispatcher.perfrorm()
ordispatcher.dispatch()
, useredux.dispatch()
bindActions
is renamed tobindActionCreators
and acceptsdispatch
as the second parameter- You may skip
composeStores
andcreateDispatcher
completely and just usecreateRedux(stores)
as a shortcut
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>
);
}
}
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>
);
}
}
// 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);
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)} />
);
}
}
0.8.1 - 2015/06/06
hydrate()
anddehydrate()
are gone, welcomegetAtom()
andsetAtom()
insteadinitialize()
anddispose()
are added for advanced use cases- changing
select
function now updates theConnector
state - the bug with action creators accepting
dispatch
instead ofperform
is fixed
0.8.0 - 2015/06/06
This release wouldn't have happened without this @acdlite's wonderful gist.
New:
- Now there is just one top Store, but you may compose your Stores using
composeStores
higher-order Store (seriously.) - Dispatcher is now part of the public API and offers (de)hydration for isomorphic apps.
- Fine-grained subscriptions via the new
<Connector select={fn}>
prop - Less surprising, more consistent API
Read the discussion: reduxjs#46
0.7.0 - 2015/06/06
- Change second parameter in callback-style action creator from
state
toread: (Store) => state
(#44) - Rename:
Container -> Injector, @container -> @inject, Root -> Dispatcher, @root -> @dispatch
(#20)
0.6.2 - 2015/06/04
@container
's second parameter now also accepts theprops
passed to it (#36)<Container />
and<Root />
invoke theirthis.props.children
functions withoutthis.props
context
0.6.1 - 2015/06/04
- Fix incorrect ES6 Map usage (#35)
0.6.0 - 2015/06/04
- Breaking change:
stores
now accepts an object, just likeactions
- Breaking change:
Container
children function signature is now({ actions, state }) => ...
- More fine-grained
Container
props validation
This fixes #22. There is no more prop shape difference between subscribing to a single or to many stores. Your container may now look like this:
<Container stores={{ counter: stores.counterStore }}
actions={{ increment, decrement }}>
{({ state, actions }) => <Counter {...state} {...actions} />}
</Container>
Note that you can change the state
shape by giving arbitrary keys to your stores. It's also easier to choose what exactly you want to pass to the component. For example, you could write actions={actions}
instead of {...actions}
, and get all actions in this.props.actions
.
The decorator version is changed the same way:
@container({
actions: { increment, decrement },
stores: { counter: counterStore }
})
export default class Counter {
It also now accepts a second transformProps
argument to be just as expressive as the component version:
@container({
actions: { increment, decrement },
stores: { counter: counterStore }
}, ({ actions, state}) => { ...actions, ...state })) // default shape; you can write your own
0.5.1 - 2015/06/03
- Fix the remaining dependency on the function name (#16)
- Add a few early invariants
0.5.0 - 2015/06/03
- Store function names are no longer significant, but you have to pass an object with all your Stores to the
root
(orRoot
). Fixes reduxjs#16
import { root } from 'redux';
import * as stores from './stores/index';
@root(stores)
export default class TodoApp {
import { root } from 'redux';
import * as stores from './stores/index';
export default class TodoApp {
render() {
return (
<Root stores={stores}>
0.4.0 - 2015/06/03
- Bring decorators back, now on top of the lower-level container components (reduxjs#15, thanks Florent)
- Require
stores
passed toContainer
to be an array - Fix build on Windows (reduxjs#11, thanks Mike)
- Reduce context footprint (reduxjs#12, thanks Florent again!)
0.3.1 - 2015/06/03
- Remove old files from build
0.3.0 - 2015/06/03
Complete rewrite.
- No more strings, now using module bindings for injecting stores and actions
- Only use decorator for top-level component, keep dumb components pure and testable (reduxjs#5)
- Remove transaction logic (will be re-implemented on top of reduxjs#6)
// The smart component may inject actions
// and observe stores using <Container />:
import React, { Component } from 'react';
import { Root, Container } from 'redux';
import { increment, decrement } from './actions/CounterActions';
import counterStore from './stores/counterStore';
import Counter from './Counter';
export default class CounterContainer {
render() {
// stores can be a single store or an array.
// actions can only be a string -> function map.
// props passed to children will combine these actions and state.
return (
<Container stores={counterStore}
actions={{ increment, decrement }}>
{props => <Counter {...props} />}
</Container>
);
}
}
Minor caveat: Store function names are now significant.
0.2.2 - 2015/06/02
- Pass
state
as a second argument to callback-style action creators
0.2.1 - 2015/06/02
- Fix
@provides
not passing its props down