From 103b614e32c73f2dc260b0f3d3b9cab5da51998e Mon Sep 17 00:00:00 2001 From: Tim Dorr Date: Mon, 1 Feb 2016 14:28:59 -0500 Subject: [PATCH 1/6] Move ActionTypes to a private export --- src/combineReducers.js | 2 +- src/createStore.js | 10 +--------- src/utils/actionTypes.js | 11 +++++++++++ test/combineReducers.spec.js | 3 ++- 4 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 src/utils/actionTypes.js diff --git a/src/combineReducers.js b/src/combineReducers.js index 36250e8d940..e4214575b39 100644 --- a/src/combineReducers.js +++ b/src/combineReducers.js @@ -1,4 +1,4 @@ -import { ActionTypes } from './createStore' +import ActionTypes from './utils/actionTypes' import isPlainObject from 'lodash/isPlainObject' import warning from './utils/warning' diff --git a/src/createStore.js b/src/createStore.js index bfe9d69123b..e81e368ae71 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -1,15 +1,7 @@ import isPlainObject from 'lodash/isPlainObject' import $$observable from 'symbol-observable' -/** - * These are private action types reserved by Redux. - * For any unknown actions, you must return the current state. - * If the current state is undefined, you must return the initial state. - * Do not reference these action types directly in your code. - */ -export const ActionTypes = { - INIT: '@@redux/INIT' -} +import ActionTypes from './utils/actionTypes' /** * Creates a Redux store that holds the state tree. diff --git a/src/utils/actionTypes.js b/src/utils/actionTypes.js new file mode 100644 index 00000000000..82c3ffedbed --- /dev/null +++ b/src/utils/actionTypes.js @@ -0,0 +1,11 @@ +/** + * These are private action types reserved by Redux. + * For any unknown actions, you must return the current state. + * If the current state is undefined, you must return the initial state. + * Do not reference these action types directly in your code. + */ +var ActionTypes = { + INIT: '@@redux/INIT' +} + +export default ActionTypes diff --git a/test/combineReducers.spec.js b/test/combineReducers.spec.js index 2fd1ab1eab2..b722a151a1e 100644 --- a/test/combineReducers.spec.js +++ b/test/combineReducers.spec.js @@ -1,6 +1,7 @@ /* eslint-disable no-console */ import { combineReducers } from '../src' -import createStore, { ActionTypes } from '../src/createStore' +import createStore from '../src/createStore' +import ActionTypes from '../src/utils/actionTypes' describe('Utils', () => { describe('combineReducers', () => { From cad6231cf2918fa2a4c00b2fb8b18c36f4558b47 Mon Sep 17 00:00:00 2001 From: Mike Wilcox Date: Tue, 19 Jul 2016 11:36:09 -0400 Subject: [PATCH 2/6] throw if getState, subscribe, or unsubscribe called while dispatching (#1569) * throw error if getState, subscribe, or unsubscribe called while dispatching * prevent throwing if not subscribed * update getState error message * fix space after period * update subscribe/unsubscribe error messages --- src/createStore.js | 24 +++++++++++++++++++++ test/createStore.spec.js | 35 +++++++++++++++++++++++++++++- test/helpers/actionCreators.js | 31 ++++++++++++++++++++++++++- test/helpers/actionTypes.js | 3 +++ test/helpers/reducers.js | 39 +++++++++++++++++++++++++++++++++- 5 files changed, 129 insertions(+), 3 deletions(-) diff --git a/src/createStore.js b/src/createStore.js index e81e368ae71..94928acd362 100644 --- a/src/createStore.js +++ b/src/createStore.js @@ -64,6 +64,14 @@ export default function createStore(reducer, preloadedState, enhancer) { * @returns {any} The current state tree of your application. */ function getState() { + if (isDispatching) { + throw new Error( + 'You may not call store.getState() while the reducer is executing. ' + + 'The reducer has already received the state as an argument. ' + + 'Pass it down from the top reducer instead of reading it from the store.' + ) + } + return currentState } @@ -95,6 +103,15 @@ export default function createStore(reducer, preloadedState, enhancer) { throw new Error('Expected listener to be a function.') } + if (isDispatching) { + throw new Error( + 'You may not call store.subscribe() while the reducer is executing. ' + + 'If you would like to be notified after the store has been updated, subscribe from a ' + + 'component and invoke store.getState() in the callback to access the latest state. ' + + 'See http://redux.js.org/docs/api/Store.html#subscribe for more details.' + ) + } + let isSubscribed = true ensureCanMutateNextListeners() @@ -105,6 +122,13 @@ export default function createStore(reducer, preloadedState, enhancer) { return } + if (isDispatching) { + throw new Error( + 'You may not unsubscribe from a store listener while the reducer is executing. ' + + 'See http://redux.js.org/docs/api/Store.html#subscribe for more details.' + ) + } + isSubscribed = false ensureCanMutateNextListeners() diff --git a/test/createStore.spec.js b/test/createStore.spec.js index c2825dd5926..336114b1eeb 100644 --- a/test/createStore.spec.js +++ b/test/createStore.spec.js @@ -1,5 +1,13 @@ import { createStore, combineReducers } from '../src/index' -import { addTodo, dispatchInMiddle, throwError, unknownAction } from './helpers/actionCreators' +import { + addTodo, + dispatchInMiddle, + getStateInMiddle, + subscribeInMiddle, + unsubscribeInMiddle, + throwError, + unknownAction +} from './helpers/actionCreators' import * as reducers from './helpers/reducers' import * as Rx from 'rxjs' import $$observable from 'symbol-observable' @@ -461,6 +469,31 @@ describe('createStore', () => { ).toThrow(/may not dispatch/) }) + it('does not allow getState() from within a reducer', () => { + const store = createStore(reducers.getStateInTheMiddleOfReducer) + + expect(() => + store.dispatch(getStateInMiddle(store.getState.bind(store))) + ).toThrow(/You may not call store.getState()/) + }) + + it('does not allow subscribe() from within a reducer', () => { + const store = createStore(reducers.subscribeInTheMiddleOfReducer) + + expect(() => + store.dispatch(subscribeInMiddle(store.subscribe.bind(store, () => {}))) + ).toThrow(/You may not call store.subscribe()/) + }) + + it('does not allow unsubscribe from subscribe() from within a reducer', () => { + const store = createStore(reducers.unsubscribeInTheMiddleOfReducer) + const unsubscribe = store.subscribe(() => {}) + + expect(() => + store.dispatch(unsubscribeInMiddle(unsubscribe.bind(store))) + ).toThrow(/You may not unsubscribe from a store/) + }) + it('recovers from an error within a reducer', () => { const store = createStore(reducers.errorThrowingReducer) expect(() => diff --git a/test/helpers/actionCreators.js b/test/helpers/actionCreators.js index 198f61be206..5c26cdcc416 100644 --- a/test/helpers/actionCreators.js +++ b/test/helpers/actionCreators.js @@ -1,4 +1,12 @@ -import { ADD_TODO, DISPATCH_IN_MIDDLE, THROW_ERROR, UNKNOWN_ACTION } from './actionTypes' +import { + ADD_TODO, + DISPATCH_IN_MIDDLE, + GET_STATE_IN_MIDDLE, + SUBSCRIBE_IN_MIDDLE, + UNSUBSCRIBE_IN_MIDDLE, + THROW_ERROR, + UNKNOWN_ACTION +} from './actionTypes' export function addTodo(text) { return { type: ADD_TODO, text } @@ -26,6 +34,27 @@ export function dispatchInMiddle(boundDispatchFn) { } } +export function getStateInMiddle(boundGetStateFn) { + return { + type: GET_STATE_IN_MIDDLE, + boundGetStateFn + } +} + +export function subscribeInMiddle(boundSubscribeFn) { + return { + type: SUBSCRIBE_IN_MIDDLE, + boundSubscribeFn + } +} + +export function unsubscribeInMiddle(boundUnsubscribeFn) { + return { + type: UNSUBSCRIBE_IN_MIDDLE, + boundUnsubscribeFn + } +} + export function throwError() { return { type: THROW_ERROR diff --git a/test/helpers/actionTypes.js b/test/helpers/actionTypes.js index 00092962f21..2e6104345c2 100644 --- a/test/helpers/actionTypes.js +++ b/test/helpers/actionTypes.js @@ -1,4 +1,7 @@ export const ADD_TODO = 'ADD_TODO' export const DISPATCH_IN_MIDDLE = 'DISPATCH_IN_MIDDLE' +export const GET_STATE_IN_MIDDLE = 'GET_STATE_IN_MIDDLE' +export const SUBSCRIBE_IN_MIDDLE = 'SUBSCRIBE_IN_MIDDLE' +export const UNSUBSCRIBE_IN_MIDDLE = 'UNSUBSCRIBE_IN_MIDDLE' export const THROW_ERROR = 'THROW_ERROR' export const UNKNOWN_ACTION = 'UNKNOWN_ACTION' diff --git a/test/helpers/reducers.js b/test/helpers/reducers.js index 8e9c7321ec8..31ce7b99e18 100644 --- a/test/helpers/reducers.js +++ b/test/helpers/reducers.js @@ -1,4 +1,11 @@ -import { ADD_TODO, DISPATCH_IN_MIDDLE, THROW_ERROR } from './actionTypes' +import { + ADD_TODO, + DISPATCH_IN_MIDDLE, + GET_STATE_IN_MIDDLE, + SUBSCRIBE_IN_MIDDLE, + UNSUBSCRIBE_IN_MIDDLE, + THROW_ERROR +} from './actionTypes' function id(state = []) { @@ -46,6 +53,36 @@ export function dispatchInTheMiddleOfReducer(state = [], action) { } } +export function getStateInTheMiddleOfReducer(state = [], action) { + switch (action.type) { + case GET_STATE_IN_MIDDLE: + action.boundGetStateFn() + return state + default: + return state + } +} + +export function subscribeInTheMiddleOfReducer(state = [], action) { + switch (action.type) { + case SUBSCRIBE_IN_MIDDLE: + action.boundSubscribeFn() + return state + default: + return state + } +} + +export function unsubscribeInTheMiddleOfReducer(state = [], action) { + switch (action.type) { + case UNSUBSCRIBE_IN_MIDDLE: + action.boundUnsubscribeFn() + return state + default: + return state + } +} + export function errorThrowingReducer(state = [], action) { switch (action.type) { case THROW_ERROR: From 5c60ef7eb3e7b41e268dd01d927a48148ea5dad5 Mon Sep 17 00:00:00 2001 From: Tim Dorr Date: Sun, 4 Sep 2016 14:01:11 -0400 Subject: [PATCH 3/6] Warn When dispatching During Middleware Setup (#1485) * Add a doc section on dispatching during middleware setup. * Warn when dispatching during middleware setup. * Upgrade the warning to an error. * Update docs to match thrown error behavior. --- docs/advanced/Middleware.md | 6 +++++- src/applyMiddleware.js | 7 ++++++- test/applyMiddleware.spec.js | 11 +++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/docs/advanced/Middleware.md b/docs/advanced/Middleware.md index fe51ff64938..f77aa88273e 100644 --- a/docs/advanced/Middleware.md +++ b/docs/advanced/Middleware.md @@ -268,12 +268,16 @@ The implementation of [`applyMiddleware()`](../api/applyMiddleware.md) that ship * It only exposes a subset of the [store API](../api/Store.md) to the middleware: [`dispatch(action)`](../api/Store.md#dispatch) and [`getState()`](../api/Store.md#getState). -* It does a bit of trickery to make sure that if you call `store.dispatch(action)` from your middleware instead of `next(action)`, the action will actually travel the whole middleware chain again, including the current middleware. This is useful for asynchronous middleware, as we have seen [previously](AsyncActions.md). +* It does a bit of trickery to make sure that if you call `store.dispatch(action)` from your middleware instead of `next(action)`, the action will actually travel the whole middleware chain again, including the current middleware. This is useful for asynchronous middleware, as we have seen [previously](AsyncActions.md). There is one caveat when calling `dispatch` during setup, described below. * To ensure that you may only apply middleware once, it operates on `createStore()` rather than on `store` itself. Instead of `(store, middlewares) => store`, its signature is `(...middlewares) => (createStore) => createStore`. Because it is cumbersome to apply functions to `createStore()` before using it, `createStore()` accepts an optional last argument to specify such functions. +#### Caveat: Dispatching During Setup + +While `applyMiddleware` executes and sets up your middleware, the `store.dispatch` function will point to the vanilla version provided by `createStore`. Dispatching would result in no other middleware being applied. If you are expecting an interaction with another middleware during setup, you will probably be disappointed. Because of this unexpected behavior, `applyMiddleware` will throw an error if you try to dispatch an action before the set up completes. Instead, you should either communicate directly with that other middleware via a common object (for an API-calling middleware, this may be your API client object) or waiting until after the middleware is constructed with a callback. + ### The Final Approach Given this middleware we just wrote: diff --git a/src/applyMiddleware.js b/src/applyMiddleware.js index 3cf08841b6d..a35098914f3 100644 --- a/src/applyMiddleware.js +++ b/src/applyMiddleware.js @@ -19,7 +19,12 @@ import compose from './compose' export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { const store = createStore(reducer, preloadedState, enhancer) - let dispatch = store.dispatch + let dispatch = () => { + throw new Error( + `Dispatching while constructing your middleware is not allowed. ` + + `Other middleware would not be applied to this dispatch.` + ) + } let chain = [] const middlewareAPI = { diff --git a/test/applyMiddleware.spec.js b/test/applyMiddleware.spec.js index c733c093b82..84e7c79df64 100644 --- a/test/applyMiddleware.spec.js +++ b/test/applyMiddleware.spec.js @@ -4,6 +4,17 @@ import { addTodo, addTodoAsync, addTodoIfEmpty } from './helpers/actionCreators' import { thunk } from './helpers/middleware' describe('applyMiddleware', () => { + it('warns when dispatching during middleware setup', () => { + function dispatchingMiddleware(store) { + store.dispatch(addTodo('Dont dispatch in middleware setup')) + return next => action => next(action) + } + + expect(() => + applyMiddleware(dispatchingMiddleware)(createStore)(reducers.todos) + ).toThrow() + }) + it('wraps dispatch method with middleware once', () => { function test(spyOnMethods) { return methods => { From 8033325697a4d1aa635a672502828c463d6f3478 Mon Sep 17 00:00:00 2001 From: Aleh Kashnikau Date: Thu, 5 Jan 2017 23:05:18 +0300 Subject: [PATCH 4/6] Mapped type for combineReducers in index.d.ts (#2182) * Add mapped type for combineReducers in index.d.ts Updated typescript to 2.1.4 Updated typescript-definition-tester to 0.0.5 Updated typescript tests to use proper import Added mapped type to index.d.ts * add strict null check for reducer Updated Reducer type in index.d.ts Add strictNullChecks flag to typescript spec --- index.d.ts | 8 ++++---- package.json | 4 ++-- test/typescript.spec.js | 3 +++ test/typescript/actionCreators.ts | 2 +- test/typescript/actions.ts | 2 +- test/typescript/compose.ts | 2 +- test/typescript/dispatch.ts | 4 ++-- test/typescript/middleware.ts | 8 ++++---- test/typescript/reducers.ts | 5 ++--- test/typescript/store.ts | 6 +++--- yarn.lock | 18 +++++++++++------- 11 files changed, 34 insertions(+), 28 deletions(-) diff --git a/index.d.ts b/index.d.ts index 88a4c0fa308..7c62f0df79d 100644 --- a/index.d.ts +++ b/index.d.ts @@ -43,13 +43,13 @@ export interface Action { * * @template S State object type. */ -export type Reducer = (state: S, action: A) => S; +export type Reducer = (state: S | undefined, action: A) => S; /** * Object whose values correspond to different reducer functions. */ -export interface ReducersMapObject { - [key: string]: Reducer; +export type ReducersMapObject = { + [K in keyof S]: Reducer; } /** @@ -70,7 +70,7 @@ export interface ReducersMapObject { * @returns A reducer function that invokes every reducer inside the passed * object, and builds a state object with the same shape. */ -export function combineReducers(reducers: ReducersMapObject): Reducer; +export function combineReducers(reducers: ReducersMapObject): Reducer; /* store */ diff --git a/package.json b/package.json index 59cfa6bb5e0..6c0632a6ad0 100644 --- a/package.json +++ b/package.json @@ -111,8 +111,8 @@ "rollup-plugin-replace": "^1.1.1", "rollup-plugin-uglify": "^1.0.1", "rxjs": "^5.0.0-beta.6", - "typescript": "^1.8.0", - "typescript-definition-tester": "0.0.4" + "typescript": "^2.1.0", + "typescript-definition-tester": "0.0.5" }, "npmName": "redux", "npmFileMap": [ diff --git a/test/typescript.spec.js b/test/typescript.spec.js index 8943a156588..de86902bb07 100644 --- a/test/typescript.spec.js +++ b/test/typescript.spec.js @@ -6,6 +6,9 @@ describe('TypeScript definitions', function () { tt.compileDirectory( __dirname + '/typescript', fileName => fileName.match(/\.ts$/), + { + strictNullChecks: true + }, () => done() ) }) diff --git a/test/typescript/actionCreators.ts b/test/typescript/actionCreators.ts index 8d8b0a1c87d..deb53bd3f91 100644 --- a/test/typescript/actionCreators.ts +++ b/test/typescript/actionCreators.ts @@ -1,7 +1,7 @@ import { ActionCreator, Action, Dispatch, bindActionCreators, ActionCreatorsMapObject -} from "../../index"; +} from "../../" interface AddTodoAction extends Action { diff --git a/test/typescript/actions.ts b/test/typescript/actions.ts index fcd05e1272d..f26fdc51765 100644 --- a/test/typescript/actions.ts +++ b/test/typescript/actions.ts @@ -1,4 +1,4 @@ -import {Action as ReduxAction} from "../../index"; +import {Action as ReduxAction} from "../../" namespace FSA { diff --git a/test/typescript/compose.ts b/test/typescript/compose.ts index 6c5c96f90c0..0866f541af6 100644 --- a/test/typescript/compose.ts +++ b/test/typescript/compose.ts @@ -1,4 +1,4 @@ -import {compose} from "../../index"; +import {compose} from "../../" // copied from DefinitelyTyped/compose-function diff --git a/test/typescript/dispatch.ts b/test/typescript/dispatch.ts index 2b456709be6..6f051421f2d 100644 --- a/test/typescript/dispatch.ts +++ b/test/typescript/dispatch.ts @@ -1,4 +1,4 @@ -import {Dispatch, Action} from "../../index"; +import {Dispatch, Action} from "../../" declare const dispatch: Dispatch; @@ -6,7 +6,7 @@ declare const dispatch: Dispatch; const dispatchResult: Action = dispatch({type: 'TYPE'}); // thunk -declare module "../../index" { +declare module "../../" { export interface Dispatch { (asyncAction: (dispatch: Dispatch, getState: () => S) => R): R; } diff --git a/test/typescript/middleware.ts b/test/typescript/middleware.ts index 3ee95a98492..b3aaf9ae9b1 100644 --- a/test/typescript/middleware.ts +++ b/test/typescript/middleware.ts @@ -1,15 +1,15 @@ import { Middleware, MiddlewareAPI, applyMiddleware, createStore, Dispatch, Reducer, Action -} from "../../index"; +} from "../../" -declare module "../../index" { +declare module "../../" { export interface Dispatch { (asyncAction: (dispatch: Dispatch, getState: () => S) => R): R; } } -type Thunk = (dispatch: Dispatch, getState: () => S) => O; +type Thunk = (dispatch: Dispatch, getState?: () => S) => O; const thunkMiddleware: Middleware = ({dispatch, getState}: MiddlewareAPI) => @@ -51,7 +51,7 @@ const storeWithThunkMiddleware = createStore( ); storeWithThunkMiddleware.dispatch( - (dispatch, getState) => { + (dispatch: Dispatch, getState: () => State) => { const todos: string[] = getState().todos; dispatch({type: 'ADD_TODO'}) } diff --git a/test/typescript/reducers.ts b/test/typescript/reducers.ts index e6068a892f5..ebf17c849e4 100644 --- a/test/typescript/reducers.ts +++ b/test/typescript/reducers.ts @@ -1,7 +1,7 @@ import { Reducer, Action, combineReducers, ReducersMapObject -} from "../../index"; +} from "../../" type TodosState = string[]; @@ -47,8 +47,7 @@ type RootState = { counter: CounterState; } - -const rootReducer: Reducer = combineReducers({ +const rootReducer: Reducer = combineReducers({ todos: todosReducer, counter: counterReducer, }) diff --git a/test/typescript/store.ts b/test/typescript/store.ts index b66e71869b2..b38bdb7efbd 100644 --- a/test/typescript/store.ts +++ b/test/typescript/store.ts @@ -1,7 +1,7 @@ import { Store, createStore, Reducer, Action, StoreEnhancer, GenericStoreEnhancer, StoreCreator, StoreEnhancerStoreCreator, Unsubscribe -} from "../../index"; +} from "../../" type State = { @@ -22,10 +22,10 @@ const storeWithPreloadedState: Store = createStore(reducer, { }); const genericEnhancer: GenericStoreEnhancer = (next: StoreEnhancerStoreCreator) => next; -const specificEnhencer: StoreEnhancer = next => next; +const specificEnhancer: StoreEnhancer = next => next; const storeWithGenericEnhancer: Store = createStore(reducer, genericEnhancer); -const storeWithSpecificEnhancer: Store = createStore(reducer, specificEnhencer); +const storeWithSpecificEnhancer: Store = createStore(reducer, specificEnhancer); const storeWithPreloadedStateAndEnhancer: Store = createStore(reducer, { todos: [] diff --git a/yarn.lock b/yarn.lock index c0d9e256d5d..4944706bc6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2610,7 +2610,11 @@ lodash.flatten@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" -lodash.isarguments@^3.0.0, lodash.isarguments@~3.0.7: +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarguments@~3.0.7: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.0.9.tgz#3c4994a4210f340d49ccfafa62176296207d8675" @@ -4143,17 +4147,17 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript-definition-tester@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/typescript-definition-tester/-/typescript-definition-tester-0.0.4.tgz#94b9edc4fe803b47f5f64ff5ddaf8eed1196156c" +typescript-definition-tester@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/typescript-definition-tester/-/typescript-definition-tester-0.0.5.tgz#91c574d78ea05b81ed81244d50ec30d8240c356f" dependencies: assertion-error "^1.0.1" dts-bundle "^0.2.0" lodash "^3.6.0" -typescript@^1.8.0: - version "1.8.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-1.8.10.tgz#b475d6e0dff0bf50f296e5ca6ef9fbb5c7320f1e" +typescript@^2.1.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.1.4.tgz#b53b69fb841126acb1dd4b397d21daba87572251" uglify-js@^2.6, uglify-js@^2.6.1: version "2.7.5" From 112a10091f6431d9dc480bd1c755cb4a98d83078 Mon Sep 17 00:00:00 2001 From: Jim Bolla Date: Thu, 5 Jan 2017 23:17:04 -0500 Subject: [PATCH 5/6] Deletes no-longer-valid applyMiddleware test. Behavior has been replaced with the "it warns when dispatching during middleware setup" test in the 'next' branch. --- test/applyMiddleware.spec.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/test/applyMiddleware.spec.js b/test/applyMiddleware.spec.js index 84e7c79df64..ec9423a8757 100644 --- a/test/applyMiddleware.spec.js +++ b/test/applyMiddleware.spec.js @@ -103,21 +103,4 @@ describe('applyMiddleware', () => { }) }) - it('keeps unwrapped dispatch available while middleware is initializing', () => { - // This is documenting the existing behavior in Redux 3.x. - // We plan to forbid this in Redux 4.x. - - function earlyDispatch({ dispatch }) { - dispatch(addTodo('Hello')) - return () => action => action - } - - const store = createStore(reducers.todos, applyMiddleware(earlyDispatch)) - expect(store.getState()).toEqual([ - { - id: 1, - text: 'Hello' - } - ]) - }) }) From 4acb40cb94767fbb854f7012715f3c1c3b1ff4a2 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Wed, 8 Mar 2017 04:45:04 +0300 Subject: [PATCH 6/6] Remove legacy jsnext entry (#2284) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 6c0632a6ad0..081a3cb1742 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "browser": "dist/redux.js", "main": "lib/index.js", "module": "es/index.js", - "jsnext:main": "es/index.js", "typings": "./index.d.ts", "files": [ "dist",