Comparing version 3.0.0 to 3.0.1
441
CHANGELOG.md
@@ -1,439 +0,4 @@ | ||
# Change log | ||
# Change Log | ||
All notable changes to this project will be documented in this file. | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
## [3.0.0](https://github.com/rackt/redux/compare/v2.0.0...v3.0.0) - 2015/09/13 | ||
### Breaking Changes | ||
* Action objects now must have a `type` property other than `undefined` ([#541](https://github.com/rackt/redux/issues/541), [#564](https://github.com/rackt/redux/pull/564)) | ||
### Other Changes | ||
* `replaceReducer()` is un-deprecated. | ||
## [2.0.0](https://github.com/rackt/redux/compare/v1.0.1...v2.0.0) - 2015/09/01 | ||
### Breaking Changes | ||
* Removes `getReducer()` from the Store public API ([#668](https://github.com/rackt/redux/issues/668)) | ||
* Fixes `compose()` to act like a normal `compose()` ([#669](https://github.com/rackt/redux/issues/669)) | ||
* Relies on `process.env.NODE_ENV` being polyfilled ([#671](https://github.com/rackt/redux/issues/671)) | ||
## [1.0.1](https://github.com/rackt/redux/compare/v1.0.0...v1.0.1) - 2015/08/15 | ||
* Fixes “process is not defined” on React Native ([#525](https://github.com/rackt/redux/issues/525), [#526](https://github.com/rackt/redux/pull/526)) | ||
* Removes dependencies on `invariant` and `warning` ([#528](https://github.com/rackt/redux/pull/528)) | ||
* Fixes TodoMVC example ([#524](https://github.com/rackt/redux/issues/524), [#529](https://github.com/rackt/redux/pull/529)) | ||
## [1.0.0](https://github.com/rackt/redux/compare/v1.0.0-rc...v1.0.0) - 2015/08/14 | ||
### Breaking Changes | ||
* 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. (https://github.com/rackt/redux/issues/368) | ||
### New Home | ||
We moved under [rackt](https://github.com/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. | ||
### Docs! | ||
[We have real docs now.](http://rackt.github.io/redux/) 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](https://github.com/GitbookIO/gitbook) for providing great tooling, too. | ||
### Examples! | ||
There's been no shortage of great examples in [Awesome Redux](https://github.com/xgrommx/awesome-redux), but we're shipping two new built-in examples in 1.0. One of them is a [very simple async application](https://github.com/rackt/redux/tree/master/examples/async). Creating it is covered in [async tutorial](http://rackt.github.io/redux/docs/advanced/AsyncActions.html). Another example we ship is a [“real-world” example](https://github.com/rackt/redux/tree/master/examples/real-world). It's a port of somewhat well-known [flux-react-router-example](https://github.com/gaearon/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. | ||
### Other Improvements | ||
* Unsubscribing during a dispatch is now fixed: https://github.com/rackt/redux/pull/462 | ||
* `bindActionCreators` now can also accept a function as the first argument: https://github.com/rackt/redux/pull/352 | ||
* Dispatching from iframe now works: https://github.com/rackt/redux/issues/304 | ||
* Symbols can be used as action types: https://github.com/rackt/redux/pull/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](https://github.com/rackt/redux/compare/v1.0.0-alpha...v1.0.0-rc) - 2015/07/13 | ||
### Big Changes | ||
* React-specific code has been moved to [react-redux](https://github.com/rackt/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 | ||
### Correctness Changes | ||
* `combineReducers` now throws if you return `undefined` state | ||
* `combineReducers` throws if you have no `default` 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.](https://github.com/rackt/redux/releases/tag/v1.0.0-rc)** | ||
## [1.0.0-alpha](https://github.com/rackt/redux/compare/v0.12.0...v1.0.0-alpha) - 2015/06/30 | ||
### Naming | ||
* “Stateless Stores” are now called reducers. (https://github.com/rackt/redux/issues/137#issuecomment-114178411) | ||
* The “Redux instance” is now called “The Store”. (https://github.com/rackt/redux/issues/137#issuecomment-113252359) | ||
* The dispatcher is removed completely. (https://github.com/rackt/redux/pull/166#issue-90113962) | ||
### API changes | ||
* <s>`composeStores`</s> is now `composeReducers`. | ||
* <s>`createDispatcher`</s> is gone. | ||
* <s>`createRedux`</s> is now `createStore`. | ||
* `<Provider>` now accepts `store` prop instead of <s>`redux`</s>. | ||
* The new `createStore` signature is `createStore(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. The `dispatch` function lets you “recurse” the middleware chain and is useful for async: #113 (comment). | ||
### Correctness changes | ||
* 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) | ||
### Internal changes | ||
* The object in React context is renamed from <s>`redux`</s> to `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.](https://github.com/rackt/redux/releases/tag/v1.0.0-alpha)** | ||
## [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` and `babel-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 to `composeMiddleware` 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`: | ||
```js | ||
// 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 if `select` returns something other than a plain object (https://github.com/rackt/redux/pull/85) | ||
* The custom dispatcher API is tweaked so `setState` now returns the state that was actually set. This makes custom dispatchers more composable. (https://github.com/rackt/redux/pull/77) | ||
Happy reducing! | ||
## [0.10.0] - 2015/06/13 | ||
### Middleware | ||
Redux 1.0 is within striking distance! Can you believe how quickly Redux has matured? @rackt made the first commit only [14 days ago](https://github.com/rackt/redux/commit/8bc14659780c044baac1432845fe1e4ca5123a8d). | ||
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](https://github.com/rackt/redux/blob/master/docs/middleware.md). We plan to release some official middleware soon, but of course we'd also love to see middleware created by the community. | ||
### Breaking changes | ||
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()`](https://github.com/rackt/redux/blob/master/src/middleware/thunk.js). It is included automatically when using the `createRedux(stores)` shortcut, but not when using `createDispatcher()`. | ||
### Tests | ||
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 | ||
### 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. | ||
```js | ||
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) => ()`. | ||
```js | ||
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 | ||
```js | ||
// 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 | ||
```js | ||
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()` and `dehydrate()` are gone, welcome `getAtom()` and `setAtom()` instead | ||
* `initialize()` and `dispose()` are added for advanced use cases | ||
* changing `select` function now updates the `Connector` state | ||
* the bug with action creators accepting `dispatch` instead of `perform` is fixed | ||
## [0.8.0] - 2015/06/06 | ||
### The Big Rewrite! | ||
This release wouldn't have happened without [this @acdlite's wonderful gist](https://gist.github.com/acdlite/9f1b5883d132ad242323). | ||
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: https://github.com/rackt/redux/pull/46 | ||
## [0.7.0] - 2015/06/06 | ||
* Change second parameter in callback-style action creator from `state` to `read: (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 the `props` passed to it (#36) | ||
* `<Container />` and `<Root />` invoke their `this.props.children` functions without `this.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 like `actions` | ||
* 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: | ||
```js | ||
<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: | ||
```js | ||
@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: | ||
```js | ||
@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` (or `Root`). Fixes https://github.com/rackt/redux/issues/16 | ||
```js | ||
import { root } from 'redux'; | ||
import * as stores from './stores/index'; | ||
@root(stores) | ||
export default class TodoApp { | ||
``` | ||
```js | ||
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 (https://github.com/rackt/redux/pull/15, thanks Florent) | ||
* Require `stores` passed to `Container` to be an array | ||
* Fix build on Windows (https://github.com/rackt/redux/pull/11, thanks Mike) | ||
* Reduce context footprint (https://github.com/rackt/redux/pull/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 (https://github.com/rackt/redux/issues/5) | ||
* Remove transaction logic (will be re-implemented on top of https://github.com/rackt/redux/issues/6) | ||
```js | ||
// 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 | ||
## 0.2.0 - 2015/06/02 | ||
* Initial public release. | ||
See examples in [README](https://github.com/rackt/redux/blob/master/README.md) and the | ||
[examples](https://github.com/rackt/redux/tree/master/examples) folder. | ||
Alpha quality :-) | ||
[unreleased]: https://github.com/rackt/redux/compare/v0.12.0...HEAD | ||
[0.12.0]: https://github.com/rackt/redux/compare/v0.11.1...v0.12.0 | ||
[0.11.1]: https://github.com/rackt/redux/compare/v0.11.0...v0.11.1 | ||
[0.11.0]: https://github.com/rackt/redux/compare/v0.10.1...v0.11.0 | ||
[0.10.1]: https://github.com/rackt/redux/compare/v0.10.0...v0.10.1 | ||
[0.10.0]: https://github.com/rackt/redux/compare/v0.9.0...v0.10.0 | ||
[0.9.0]: https://github.com/rackt/redux/compare/v0.8.1...v0.9.0 | ||
[0.8.1]: https://github.com/rackt/redux/compare/v0.8.0...v0.8.1 | ||
[0.8.0]: https://github.com/rackt/redux/compare/v0.7.0...v0.8.0 | ||
[0.7.0]: https://github.com/rackt/redux/compare/v0.6.2...v0.7.0 | ||
[0.6.2]: https://github.com/rackt/redux/compare/v0.6.1...v0.6.2 | ||
[0.6.1]: https://github.com/rackt/redux/compare/v0.6.0...v0.6.1 | ||
[0.6.0]: https://github.com/rackt/redux/compare/v0.5.1...v0.6.0 | ||
[0.5.1]: https://github.com/rackt/redux/compare/v0.5.0...v0.5.1 | ||
[0.5.0]: https://github.com/rackt/redux/compare/v0.4.0...v0.5.0 | ||
[0.4.0]: https://github.com/rackt/redux/compare/v0.3.1...v0.4.0 | ||
[0.3.1]: https://github.com/rackt/redux/compare/v0.3.0...v0.3.1 | ||
[0.3.0]: https://github.com/rackt/redux/compare/v0.2.2...v0.3.0 | ||
[0.2.2]: https://github.com/rackt/redux/compare/v0.2.1...v0.2.2 | ||
[0.2.1]: https://github.com/rackt/redux/compare/v0.2.0...v0.2.1 | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
Every release, along with the migration instructions, is documented on the Github [Releases](https://github.com/rackt/redux/releases) page. |
@@ -260,3 +260,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
* @returns {Function} A function obtained by composing functions from right to | ||
* left. For example, compose(f, g, h) is identical to x => h(g(f(x))). | ||
* left. For example, compose(f, g, h) is identical to arg => f(g(h(arg))). | ||
*/ | ||
@@ -502,4 +502,5 @@ "use strict"; | ||
function verifyStateShape(initialState, currentState) { | ||
var reducerKeys = Object.keys(currentState); | ||
function verifyStateShape(inputState, outputState, action) { | ||
var reducerKeys = Object.keys(outputState); | ||
var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'initialState argument passed to createStore' : 'previous state received by the reducer'; | ||
@@ -511,8 +512,8 @@ if (reducerKeys.length === 0) { | ||
if (!_utilsIsPlainObject2['default'](initialState)) { | ||
console.error('initialState has unexpected type of "' + ({}).toString.call(initialState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected initialState to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"')); | ||
if (!_utilsIsPlainObject2['default'](inputState)) { | ||
console.error('The ' + argumentName + ' has unexpected type of "' + ({}).toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"')); | ||
return; | ||
} | ||
var unexpectedKeys = Object.keys(initialState).filter(function (key) { | ||
var unexpectedKeys = Object.keys(inputState).filter(function (key) { | ||
return reducerKeys.indexOf(key) < 0; | ||
@@ -522,3 +523,3 @@ }); | ||
if (unexpectedKeys.length > 0) { | ||
console.error('Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" in initialState will be ignored. ') + ('Expected to find one of the known reducer keys instead: "' + reducerKeys.join('", "') + '"')); | ||
console.error('Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.')); | ||
} | ||
@@ -548,12 +549,13 @@ } | ||
}); | ||
var sanityError; | ||
Object.keys(finalReducers).forEach(function (key) { | ||
var reducer = finalReducers[key]; | ||
if (typeof reducer(undefined, { type: _createStore.ActionTypes.INIT }) === 'undefined') { | ||
throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.'); | ||
if (!sanityError && typeof reducer(undefined, { type: _createStore.ActionTypes.INIT }) === 'undefined') { | ||
sanityError = new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.'); | ||
} | ||
var type = Math.random().toString(36).substring(7).split('').join('.'); | ||
if (typeof reducer(undefined, { type: type }) === 'undefined') { | ||
throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.'); | ||
var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.'); | ||
if (!sanityError && typeof reducer(undefined, { type: type }) === 'undefined') { | ||
sanityError = new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.'); | ||
} | ||
@@ -565,3 +567,2 @@ }); | ||
}); | ||
var stateShapeVerified; | ||
@@ -571,2 +572,5 @@ return function combination(state, action) { | ||
if (sanityError) { | ||
throw sanityError; | ||
} | ||
var finalState = _utilsMapValues2['default'](finalReducers, function (reducer, key) { | ||
@@ -581,6 +585,3 @@ var newState = reducer(state[key], action); | ||
if (true) { | ||
if (!stateShapeVerified) { | ||
verifyStateShape(state, finalState); | ||
stateShapeVerified = true; | ||
} | ||
verifyStateShape(state, finalState, action); | ||
} | ||
@@ -587,0 +588,0 @@ |
@@ -1,1 +0,1 @@ | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Redux=e():t.Redux=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}e.__esModule=!0;var o=n(1),u=r(o),i=n(7),a=r(i),f=n(6),c=r(f),d=n(5),s=r(d),l=n(2),p=r(l);e.createStore=u.default,e.combineReducers=a.default,e.bindActionCreators=c.default,e.applyMiddleware=s.default,e.compose=p.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){function n(){return c}function r(t){return d.push(t),function(){var e=d.indexOf(t);d.splice(e,1)}}function o(t){if(!i.default(t))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if("undefined"==typeof t.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(s)throw new Error("Reducers may not dispatch actions.");try{s=!0,c=f(c,t)}finally{s=!1}return d.slice().forEach(function(t){return t()}),t}function u(t){f=t,o({type:a.INIT})}if("function"!=typeof t)throw new Error("Expected the reducer to be a function.");var f=t,c=e,d=[],s=!1;return o({type:a.INIT}),{dispatch:o,subscribe:r,getState:n,replaceReducer:u}}e.__esModule=!0,e.default=o;var u=n(3),i=r(u),a={INIT:"@@redux/INIT"};e.ActionTypes=a},function(t,e){"use strict";function n(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];return function(t){return e.reduceRight(function(t,e){return e(t)},t)}}e.__esModule=!0,e.default=n,t.exports=e.default},function(t,e){"use strict";function n(t){if(!t||"object"!=typeof t)return!1;var e="function"==typeof t.constructor?Object.getPrototypeOf(t):Object.prototype;if(null===e)return!0;var n=e.constructor;return"function"==typeof n&&n instanceof n&&r(n)===r(Object)}e.__esModule=!0,e.default=n;var r=function(t){return Function.prototype.toString.call(t)};t.exports=e.default},function(t,e){"use strict";function n(t,e){return Object.keys(t).reduce(function(n,r){return n[r]=e(t[r],r),n},{})}e.__esModule=!0,e.default=n,t.exports=e.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];return function(t){return function(n,r){var o=t(n,r),i=o.dispatch,f=[],c={getState:o.getState,dispatch:function(t){return i(t)}};return f=e.map(function(t){return t(c)}),i=a.default.apply(void 0,f)(o.dispatch),u({},o,{dispatch:i})}}}e.__esModule=!0;var u=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t};e.default=o;var i=n(2),a=r(i);t.exports=e.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){return function(){return e(t.apply(void 0,arguments))}}function u(t,e){if("function"==typeof t)return o(t,e);if("object"!=typeof t||null===t||void 0===t)throw new Error("bindActionCreators expected an object or a function, instead received "+(null===t?"null":typeof t)+'. Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?');return a.default(t,function(t){return o(t,e)})}e.__esModule=!0,e.default=u;var i=n(4),a=r(i);t.exports=e.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function o(t,e){var n=e&&e.type,r=n&&'"'+n.toString()+'"'||"an action";return'Reducer "'+t+'" returned undefined handling '+r+". To ignore an action, you must explicitly return the previous state."}function u(t){var e=s.default(t,function(t){return"function"==typeof t});Object.keys(e).forEach(function(t){var n=e[t];if("undefined"==typeof n(void 0,{type:i.ActionTypes.INIT}))throw new Error('Reducer "'+t+'" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined.');var r=Math.random().toString(36).substring(7).split("").join(".");if("undefined"==typeof n(void 0,{type:r}))throw new Error('Reducer "'+t+'" returned undefined when probed with a random type. '+("Don't try to handle "+i.ActionTypes.INIT+' or other actions in "redux/*" ')+"namespace. They are considered private. Instead, you must return the current state for any unknown actions, unless it is undefined, in which case you must return the initial state, regardless of the action type. The initial state may not be undefined.")});var n=c.default(e,function(){return void 0});return function(t,r){void 0===t&&(t=n);var u=c.default(e,function(e,n){var u=e(t[n],r);if("undefined"==typeof u)throw new Error(o(n,r));return u});return u}}e.__esModule=!0,e.default=u;var i=n(1),a=n(3),f=(r(a),n(4)),c=r(f),d=n(8),s=r(d);t.exports=e.default},function(t,e){"use strict";function n(t,e){return Object.keys(t).reduce(function(n,r){return e(t[r])&&(n[r]=t[r]),n},{})}e.__esModule=!0,e.default=n,t.exports=e.default}])}); | ||
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.Redux=e():t.Redux=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var u=n[r]={exports:{},id:r,loaded:!1};return t[r].call(u.exports,u,u.exports,e),u.loaded=!0,u.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}e.__esModule=!0;var u=n(1),o=r(u),i=n(7),a=r(i),f=n(6),c=r(f),d=n(5),s=r(d),l=n(2),p=r(l);e.createStore=o.default,e.combineReducers=a.default,e.bindActionCreators=c.default,e.applyMiddleware=s.default,e.compose=p.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function u(t,e){function n(){return c}function r(t){return d.push(t),function(){var e=d.indexOf(t);d.splice(e,1)}}function u(t){if(!i.default(t))throw new Error("Actions must be plain objects. Use custom middleware for async actions.");if("undefined"==typeof t.type)throw new Error('Actions may not have an undefined "type" property. Have you misspelled a constant?');if(s)throw new Error("Reducers may not dispatch actions.");try{s=!0,c=f(c,t)}finally{s=!1}return d.slice().forEach(function(t){return t()}),t}function o(t){f=t,u({type:a.INIT})}if("function"!=typeof t)throw new Error("Expected the reducer to be a function.");var f=t,c=e,d=[],s=!1;return u({type:a.INIT}),{dispatch:u,subscribe:r,getState:n,replaceReducer:o}}e.__esModule=!0,e.default=u;var o=n(3),i=r(o),a={INIT:"@@redux/INIT"};e.ActionTypes=a},function(t,e){"use strict";function n(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];return function(t){return e.reduceRight(function(t,e){return e(t)},t)}}e.__esModule=!0,e.default=n,t.exports=e.default},function(t,e){"use strict";function n(t){if(!t||"object"!=typeof t)return!1;var e="function"==typeof t.constructor?Object.getPrototypeOf(t):Object.prototype;if(null===e)return!0;var n=e.constructor;return"function"==typeof n&&n instanceof n&&r(n)===r(Object)}e.__esModule=!0,e.default=n;var r=function(t){return Function.prototype.toString.call(t)};t.exports=e.default},function(t,e){"use strict";function n(t,e){return Object.keys(t).reduce(function(n,r){return n[r]=e(t[r],r),n},{})}e.__esModule=!0,e.default=n,t.exports=e.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function u(){for(var t=arguments.length,e=Array(t),n=0;t>n;n++)e[n]=arguments[n];return function(t){return function(n,r){var u=t(n,r),i=u.dispatch,f=[],c={getState:u.getState,dispatch:function(t){return i(t)}};return f=e.map(function(t){return t(c)}),i=a.default.apply(void 0,f)(u.dispatch),o({},u,{dispatch:i})}}}e.__esModule=!0;var o=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t};e.default=u;var i=n(2),a=r(i);t.exports=e.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function u(t,e){return function(){return e(t.apply(void 0,arguments))}}function o(t,e){if("function"==typeof t)return u(t,e);if("object"!=typeof t||null===t||void 0===t)throw new Error("bindActionCreators expected an object or a function, instead received "+(null===t?"null":typeof t)+'. Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?');return a.default(t,function(t){return u(t,e)})}e.__esModule=!0,e.default=o;var i=n(4),a=r(i);t.exports=e.default},function(t,e,n){"use strict";function r(t){return t&&t.__esModule?t:{"default":t}}function u(t,e){var n=e&&e.type,r=n&&'"'+n.toString()+'"'||"an action";return'Reducer "'+t+'" returned undefined handling '+r+". To ignore an action, you must explicitly return the previous state."}function o(t){var e,n=s.default(t,function(t){return"function"==typeof t});Object.keys(n).forEach(function(t){var r=n[t];e||"undefined"!=typeof r(void 0,{type:i.ActionTypes.INIT})||(e=new Error('Reducer "'+t+'" returned undefined during initialization. If the state passed to the reducer is undefined, you must explicitly return the initial state. The initial state may not be undefined.'));var u="@@redux/PROBE_UNKNOWN_ACTION_"+Math.random().toString(36).substring(7).split("").join(".");e||"undefined"!=typeof r(void 0,{type:u})||(e=new Error('Reducer "'+t+'" returned undefined when probed with a random type. '+("Don't try to handle "+i.ActionTypes.INIT+' or other actions in "redux/*" ')+"namespace. They are considered private. Instead, you must return the current state for any unknown actions, unless it is undefined, in which case you must return the initial state, regardless of the action type. The initial state may not be undefined."))});var r=c.default(n,function(){return void 0});return function(t,o){if(void 0===t&&(t=r),e)throw e;var i=c.default(n,function(e,n){var r=e(t[n],o);if("undefined"==typeof r)throw new Error(u(n,o));return r});return i}}e.__esModule=!0,e.default=o;var i=n(1),a=n(3),f=(r(a),n(4)),c=r(f),d=n(8),s=r(d);t.exports=e.default},function(t,e){"use strict";function n(t,e){return Object.keys(t).reduce(function(n,r){return e(t[r])&&(n[r]=t[r]),n},{})}e.__esModule=!0,e.default=n,t.exports=e.default}])}); |
@@ -31,4 +31,5 @@ 'use strict'; | ||
function verifyStateShape(initialState, currentState) { | ||
var reducerKeys = Object.keys(currentState); | ||
function verifyStateShape(inputState, outputState, action) { | ||
var reducerKeys = Object.keys(outputState); | ||
var argumentName = action && action.type === _createStore.ActionTypes.INIT ? 'initialState argument passed to createStore' : 'previous state received by the reducer'; | ||
@@ -40,8 +41,8 @@ if (reducerKeys.length === 0) { | ||
if (!_utilsIsPlainObject2['default'](initialState)) { | ||
console.error('initialState has unexpected type of "' + ({}).toString.call(initialState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected initialState to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"')); | ||
if (!_utilsIsPlainObject2['default'](inputState)) { | ||
console.error('The ' + argumentName + ' has unexpected type of "' + ({}).toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + '". Expected argument to be an object with the following ' + ('keys: "' + reducerKeys.join('", "') + '"')); | ||
return; | ||
} | ||
var unexpectedKeys = Object.keys(initialState).filter(function (key) { | ||
var unexpectedKeys = Object.keys(inputState).filter(function (key) { | ||
return reducerKeys.indexOf(key) < 0; | ||
@@ -51,3 +52,3 @@ }); | ||
if (unexpectedKeys.length > 0) { | ||
console.error('Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" in initialState will be ignored. ') + ('Expected to find one of the known reducer keys instead: "' + reducerKeys.join('", "') + '"')); | ||
console.error('Unexpected ' + (unexpectedKeys.length > 1 ? 'keys' : 'key') + ' ' + ('"' + unexpectedKeys.join('", "') + '" found in ' + argumentName + '. ') + 'Expected to find one of the known reducer keys instead: ' + ('"' + reducerKeys.join('", "') + '". Unexpected keys will be ignored.')); | ||
} | ||
@@ -77,12 +78,13 @@ } | ||
}); | ||
var sanityError; | ||
Object.keys(finalReducers).forEach(function (key) { | ||
var reducer = finalReducers[key]; | ||
if (typeof reducer(undefined, { type: _createStore.ActionTypes.INIT }) === 'undefined') { | ||
throw new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.'); | ||
if (!sanityError && typeof reducer(undefined, { type: _createStore.ActionTypes.INIT }) === 'undefined') { | ||
sanityError = new Error('Reducer "' + key + '" returned undefined during initialization. ' + 'If the state passed to the reducer is undefined, you must ' + 'explicitly return the initial state. The initial state may ' + 'not be undefined.'); | ||
} | ||
var type = Math.random().toString(36).substring(7).split('').join('.'); | ||
if (typeof reducer(undefined, { type: type }) === 'undefined') { | ||
throw new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.'); | ||
var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.'); | ||
if (!sanityError && typeof reducer(undefined, { type: type }) === 'undefined') { | ||
sanityError = new Error('Reducer "' + key + '" returned undefined when probed with a random type. ' + ('Don\'t try to handle ' + _createStore.ActionTypes.INIT + ' or other actions in "redux/*" ') + 'namespace. They are considered private. Instead, you must return the ' + 'current state for any unknown actions, unless it is undefined, ' + 'in which case you must return the initial state, regardless of the ' + 'action type. The initial state may not be undefined.'); | ||
} | ||
@@ -94,3 +96,2 @@ }); | ||
}); | ||
var stateShapeVerified; | ||
@@ -100,2 +101,5 @@ return function combination(state, action) { | ||
if (sanityError) { | ||
throw sanityError; | ||
} | ||
var finalState = _utilsMapValues2['default'](finalReducers, function (reducer, key) { | ||
@@ -110,6 +114,3 @@ var newState = reducer(state[key], action); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!stateShapeVerified) { | ||
verifyStateShape(state, finalState); | ||
stateShapeVerified = true; | ||
} | ||
verifyStateShape(state, finalState, action); | ||
} | ||
@@ -116,0 +117,0 @@ |
@@ -6,3 +6,3 @@ /** | ||
* @returns {Function} A function obtained by composing functions from right to | ||
* left. For example, compose(f, g, h) is identical to x => h(g(f(x))). | ||
* left. For example, compose(f, g, h) is identical to arg => f(g(h(arg))). | ||
*/ | ||
@@ -9,0 +9,0 @@ "use strict"; |
{ | ||
"name": "redux", | ||
"version": "3.0.0", | ||
"version": "3.0.1", | ||
"description": "Predictable state container for JavaScript apps", | ||
@@ -67,4 +67,3 @@ "main": "lib/index.js", | ||
"rimraf": "^2.3.4", | ||
"webpack": "^1.9.6", | ||
"webpack-dev-server": "^1.8.2" | ||
"webpack": "^1.9.6" | ||
}, | ||
@@ -71,0 +70,0 @@ "npmName": "redux", |
@@ -10,4 +10,4 @@ # [Redux](http://rackt.github.io/redux) | ||
[![build status](https://img.shields.io/travis/rackt/redux/master.svg?style=flat-square)](https://travis-ci.org/rackt/redux) | ||
[![npm version](https://img.shields.io/npm/v/redux.svg?style=flat-square)](https://www.npmjs.com/package/redux) | ||
[![build status](https://img.shields.io/travis/rackt/redux/master.svg?style=flat-square)](https://travis-ci.org/rackt/redux) | ||
[![npm version](https://img.shields.io/npm/v/redux.svg?style=flat-square)](https://www.npmjs.com/package/redux) | ||
[![npm downloads](https://img.shields.io/npm/dm/redux.svg?style=flat-square)](https://www.npmjs.com/package/redux) | ||
@@ -124,3 +124,3 @@ [![redux channel on slack](https://img.shields.io/badge/slack-redux@reactiflux-61DAFB.svg?style=flat-square)](http://www.reactiflux.com) | ||
For PDF, ePub, and MOBI exports for offline reading, and instructions on how to create them, please see: [paulwittmann/redux-offline-docs](https://github.com/paulwittmann/redux-offline-docs). | ||
For PDF, ePub, and MOBI exports for offline reading, and instructions on how to create them, please see: [paulkogel/redux-offline-docs](https://github.com/paulkogel/redux-offline-docs). | ||
@@ -131,3 +131,5 @@ ### Examples | ||
* [TodoMVC](http://rackt.github.io/redux/docs/introduction/Examples.html#todomvc) ([source](https://github.com/rackt/redux/tree/master/examples/todomvc)) | ||
* [Todos with Undo](http://rackt.github.io/redux/docs/introduction/Examples.html#todos-with-undo) ([source](https://github.com/rackt/redux/tree/master/examples/todos-with-undo)) | ||
* [Async](http://rackt.github.io/redux/docs/introduction/Examples.html#async) ([source](https://github.com/rackt/redux/tree/master/examples/async)) | ||
* [Universal](http://rackt.github.io/redux/docs/introduction/Examples.html#universal) ([source](https://github.com/rackt/redux/tree/master/examples/universal)) | ||
* [Real World](http://rackt.github.io/redux/docs/introduction/Examples.html#real-world) ([source](https://github.com/rackt/redux/tree/master/examples/real-world)) | ||
@@ -156,2 +158,7 @@ | ||
### Change Log | ||
This project adheres to [Semantic Versioning](http://semver.org/). | ||
Every release, along with the migration instructions, is documented on the Github [Releases](https://github.com/rackt/redux/releases) page. | ||
### Patrons | ||
@@ -158,0 +165,0 @@ |
@@ -18,4 +18,7 @@ import { ActionTypes } from '../createStore'; | ||
function verifyStateShape(initialState, currentState) { | ||
var reducerKeys = Object.keys(currentState); | ||
function verifyStateShape(inputState, outputState, action) { | ||
var reducerKeys = Object.keys(outputState); | ||
var argumentName = action && action.type === ActionTypes.INIT ? | ||
'initialState argument passed to createStore' : | ||
'previous state received by the reducer'; | ||
@@ -30,7 +33,7 @@ if (reducerKeys.length === 0) { | ||
if (!isPlainObject(initialState)) { | ||
if (!isPlainObject(inputState)) { | ||
console.error( | ||
'initialState has unexpected type of "' + | ||
({}).toString.call(initialState).match(/\s([a-z|A-Z]+)/)[1] + | ||
'". Expected initialState to be an object with the following ' + | ||
`The ${argumentName} has unexpected type of "` + | ||
({}).toString.call(inputState).match(/\s([a-z|A-Z]+)/)[1] + | ||
`". Expected argument to be an object with the following ` + | ||
`keys: "${reducerKeys.join('", "')}"` | ||
@@ -41,3 +44,3 @@ ); | ||
var unexpectedKeys = Object.keys(initialState).filter( | ||
var unexpectedKeys = Object.keys(inputState).filter( | ||
key => reducerKeys.indexOf(key) < 0 | ||
@@ -49,4 +52,5 @@ ); | ||
`Unexpected ${unexpectedKeys.length > 1 ? 'keys' : 'key'} ` + | ||
`"${unexpectedKeys.join('", "')}" in initialState will be ignored. ` + | ||
`Expected to find one of the known reducer keys instead: "${reducerKeys.join('", "')}"` | ||
`"${unexpectedKeys.join('", "')}" found in ${argumentName}. ` + | ||
`Expected to find one of the known reducer keys instead: ` + | ||
`"${reducerKeys.join('", "')}". Unexpected keys will be ignored.` | ||
); | ||
@@ -75,7 +79,8 @@ } | ||
var finalReducers = pick(reducers, (val) => typeof val === 'function'); | ||
var sanityError; | ||
Object.keys(finalReducers).forEach(key => { | ||
var reducer = finalReducers[key]; | ||
if (typeof reducer(undefined, { type: ActionTypes.INIT }) === 'undefined') { | ||
throw new Error( | ||
if (!sanityError && typeof reducer(undefined, { type: ActionTypes.INIT }) === 'undefined') { | ||
sanityError = new Error( | ||
`Reducer "${key}" returned undefined during initialization. ` + | ||
@@ -88,5 +93,5 @@ `If the state passed to the reducer is undefined, you must ` + | ||
var type = Math.random().toString(36).substring(7).split('').join('.'); | ||
if (typeof reducer(undefined, { type }) === 'undefined') { | ||
throw new Error( | ||
var type = '@@redux/PROBE_UNKNOWN_ACTION_' + Math.random().toString(36).substring(7).split('').join('.'); | ||
if (!sanityError && typeof reducer(undefined, { type }) === 'undefined') { | ||
sanityError = new Error( | ||
`Reducer "${key}" returned undefined when probed with a random type. ` + | ||
@@ -103,5 +108,7 @@ `Don't try to handle ${ActionTypes.INIT} or other actions in "redux/*" ` + | ||
var defaultState = mapValues(finalReducers, () => undefined); | ||
var stateShapeVerified; | ||
return function combination(state = defaultState, action) { | ||
if (sanityError) { | ||
throw sanityError; | ||
} | ||
var finalState = mapValues(finalReducers, (reducer, key) => { | ||
@@ -116,6 +123,3 @@ var newState = reducer(state[key], action); | ||
if (process.env.NODE_ENV !== 'production') { | ||
if (!stateShapeVerified) { | ||
verifyStateShape(state, finalState); | ||
stateShapeVerified = true; | ||
} | ||
verifyStateShape(state, finalState, action); | ||
} | ||
@@ -122,0 +126,0 @@ |
@@ -6,3 +6,3 @@ /** | ||
* @returns {Function} A function obtained by composing functions from right to | ||
* left. For example, compose(f, g, h) is identical to x => h(g(f(x))). | ||
* left. For example, compose(f, g, h) is identical to arg => f(g(h(arg))). | ||
*/ | ||
@@ -9,0 +9,0 @@ export default function compose(...funcs) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
14
1324
173
77609