Skip to content

Releases: redux-loop/redux-loop

4.2.1

06 Oct 15:59
Compare
Choose a tag to compare

Bugfix: fix imports in merge-child-reducers so that they don't explicitly pull from src, which breaks builds.

4.2.0

06 Oct 07:21
Compare
Choose a tag to compare

New feature: mergeChildReducers

combineReducers is great for the case where your parent reducer has no functionality of its own, just children. However, it's often the case that you want to nest a specific reducer inside a generic parent reducer.

mergeChildReducers lets you do this. It merges child reducer state into the parent state while
composing any Cmds returned by any of the reducers and passing them along to the store.

const initialState = {foo: null};

function parentReducer(state = initialState, action){
  //typical reducer
}

export default function reducer(state, action){
   let parentResult = parentReducer(state, action);
   return mergeChildReducers(parentResult, action, {child: childReducer});
}

//final state shape is {foo, child}; foo.child is state returned by childReducer

See the docs for more detailed instructions for using mergeChildReducers.

Deprecating custom combineReducers

We are deprecating the customization parameters that you can currently pass to combineReducers in favor of moving customized versions of combineReducers into separate packages. After the next major version bump, the combineReducers in core redux-loop will only support plain JS objects as reducer maps and no extra parameters. ImmutableJS integration has been broken out into the redux-loop-immutable package.

This is due to the fact that it is impossible to have an optimal combineReducers implementation that is also generic enough to support different object shapes and types. In the case of immutableJS, the generic version could not use withMutations and so it would create a new object for each key it iterated over.

In general going forward, if combineReducers and mergeChildReducers do not fit your needs, we encourage you to write your own helpers to compose reducers that fit your specific needs. The only requirement for redux-loop is that they pull the commands out of the child results and batch them together into a single Cmd to be passed along in the resulting loop object. See the mergeChildReducers and combineReducers implementations for reference.

If you have a popular use case or library that is not currently supported, please file an issue and we can discuss if it makes sense for us to support a custom integration.

New Feature: Simulating Cmds

Occasionally you may find yourself in a situation where you need to pass more than one parameter to an action creator, such as:

Cmd.run(foo, {
  successActionCreator: foo => actionCreator(foo, state.blah)
})

Testing these cmds can be difficult: You can't do a deep equality check because the success action creator is always a new instance of the function. Instead, you can simulate the cmd to test the action creators.

import { Cmd, getCmd, getModel } from 'redux-loop';
...

let result = reducer(state, action);
expect(getModel(result)).toEqual(whatever);
let cmd = getCmd(result);

//test the rest of the cmd
expect(cmd).toEqual(Cmd.run(foo, {
  successActionCreator: jasmine.any(Function) //replace with your testing library's equivalent matcher
}));

expect(cmd.simulate({success: true, result: 123})).toEqual(actionCreator(123, state.blah));
expect(cmd.simulate({success: false, result: 123})).toBe(null);

You can simulate any Cmd to test the actions returned. Lists take arrays of simulations for their child cmds.

See detailed documentation about simulating Cmds

New Feature: Testing subsets of List Cmds

Normally, if the first parameter to Cmd.list is not an array of Cmds, an error will be thrown (unless you are in production). You can turn this off in testing environments by using the new option testInvariants. NOTE: ONLY DO THIS IN TESTS. IF YOU DO THIS IN PRODUCTION, IT WILL THROW AN EXCEPTION. This is useful if you want to pass a custom object from your test library to verify a subset of cmds, such as jasmine.arrayContaining(someCmd).

Example:

let cmd = getCmd(reducer(state, action));
const expectedCmd = Cmd.run(foo);
expect(cmd).toEqual(Cmd.list(jasmine.arrayContaining(expectedCmd), {testInvariants: true}));

4.1.0

30 Sep 03:44
Compare
Choose a tag to compare

Cmd.list

Cmd.list is a new Cmd type that replaces Cmd.batch and Cmd.sequence and exposes new behavior. Batch and Sequence will remain in the API (with a deprecation warning) until v5, and then they will be removed.

The usage of Cmd.list is similar to both batch and sequence. Its signature is Cmd.list(cmds, options). Cmds is still just an array of other Cmds. Options currently has 2 optional properties.

  • sequence: a boolean that determines whether asynchronous Cmds run in parallel or one after the other. By default, this is false.
  • batch: a boolean that determines whether each action from a nested Cmd is dispatched as soon as that Cmd is done processing or all at once (in the original Cmd order) after everything is done. By default, this is false.

To mimic the behavior of Cmd.batch(cmds) with a list, you would say Cmd.list(cmds, {batch: true, sequence: false}).

To mimic the behavior of Cmd.sequence(cmds) with a list, you would say Cmd.list(cmds, {batch: true, sequence: true}).

Since batching actions delays updates to the app and gives the appearance of worse performance, it is recommended to only use it when needed. The same applies to running them in sequence instead of parallel (the default).

4.0.2

22 Sep 03:25
Compare
Choose a tag to compare

Bugfix: Fix typo in typescript typing.
Bugfix: Add missing option for Cmd.run in typescript typing

4.0.1

22 Sep 01:58
Compare
Choose a tag to compare

Bugfix: Remove extra files from the package.

4.0.0

22 Sep 01:57
Compare
Choose a tag to compare

Breaking Changes:

  • Deprecated functionality has been removed (Effects, Cmd.constant, Cmd.call, Cmd.promise, and Cmd.arbitrary). Anything that gave a warning in version 3. If you had no warnings in v3, you should be fine.
  • Build changes: The module/jsnext:main build is now transpiled down to es5 (except for imports and exports), and has also changed locations. A UMD build is also now available in the dist folder.
    • These changes should have no effect on the majority of projects. They should only have an effect If you were depending directly on the old folder location for the es6 build or depending on it not being transpiled.

Other changes:

  • Tests have been moved from tape to jest.
  • ESLint has been added and is now required to pass for a successful build of the library. Rules are the same as create-react-app, which is also used in redux.

3.2.2

22 Sep 03:26
Compare
Choose a tag to compare

Bugfix: Fix typo in typescript typing.
Bugfix: Add missing option for Cmd.run in typescript typing

3.2.1

20 Sep 14:44
Compare
Choose a tag to compare

Bugfix: Fix combineReducers typescript definition to not require all children to be of the same type. Thanks @jaredklewis !

3.2.0

12 Sep 15:36
Compare
Choose a tag to compare

New Feature: Typescript typings added. Thank you to @willisplummer for getting this done!

3.1.2

08 Aug 15:07
Compare
Choose a tag to compare

Bugfix: Fix import causing undefined error