Skip to content

v0.10.0

Compare
Choose a tag to compare
@jeffbski jeffbski released this 18 Nov 19:22
· 269 commits to master since this release

Possible breaking changes

It is unlikely that these changes would introduce problems in most codebases but since there is a possibility so I wanted to call them out.

  • Several methods now throw errors if passed logic that is duplicated (same exact instance) since this is most likely a misconfiguration in your code. You can clone the logic with Object.assign or similar to create multiple instances if you really need to have the same logic multiple times in the stack.
    • createLogicMiddleware(arrLogic, deps) - arrLogic is expected to have unique logic instances
    • logicMiddleware.addLogic(arrLogic) - arrLogic needs to be unique and not contain any instances that were already present in the logic stack
    • logicMiddleware.replaceLogic(arrLogic) - arrLogic needs to be unique instances
  • A new method is added which will check the array of logic and only merge in new items was added. This makes it easy to work with split bundles. If the logic already exists in the stack then it will be filtered out of the merge so only new items are added.
    • logicMiddleware.mergeNewLogic(arrLogic) - will check whether logic already exists in the stack merging only the new ones into the stack.
  • Use arity of process fn signature to determine the default dispatching mode (single, multiple, dispatchReturn) to make use more intuitive.

With v0.10.0 process has the following fn signature

process({ getState, action }, ?dispatch, ?done)

which results in the following three possible variations:

// dispatch from returned object, resolved promise, or observable
// this defaults processOptions.dispatchReturn = true enabling
// dispatching of the returned/resolved values
process({ getState, action }) {
  return objOrPromiseOrObservable;
}
// single dispatch
process({ getState, action }, dispatch) {
  dispatch(objOrPromiseOrObservable); // call exactly once
}
// multiple dispatch, call done when finished dispatching
// this defaults processOptions.dispatchMultiple = true
// which enables the multiple dispatch mode
process({ getState, action }, dispatch, done) {
  dispatch(objOrPromiseOrObservable);
  dispatch(objOrPromiseOrObservable);
  done(); // call when done dispatching
}

Basically the arity of the function you provide for process determines the default values for a couple processOptions: dispatchReturn and dispatchMultiple. You can still set these values directly or just let them be inferred by the arity of process.

There is more discussion in the advanced section of the API docs.

Note: the previous v0.9 mechanism for multiple dispatches setting the second parameter of the dispatch function to {allowMore: true} will also work but is deprecated in lieu of this simpler arity approach.

New features

  • logic name property can be used to provide a meaningful name to logic. This property defaults to L(actionType)-idx if one is not provided. Technically name was already available but it wasn't documented until now.
  • processOptions.dispatchMultiple - drives whether process is in single dispatch mode or multiple dispatch mode. When false, it is single dispatch mode, dispatch is expected to be called exactly once and when true, multi-dispatch mode is enabled where dispatch can be used any number of times until the done cb is called to complete. The default is driven by whether the process fn has the done parameter. See the advanced section of the API for more details.
  • logicMiddleware.whenComplete(fn) - for server-side use, logicMiddleware can let you know when all your dispatched actions and all their processing has completed so you can serialize the state and send it to the server.
// for server-side use, runs optional fn and returns promise
// when all in-flight processing/loading has completed.
// Use it after performing any required store.dispatch
store.dispatch(ROUTE_CHANGE); // triggers async loading in our logic
store.dispatch(FOO); // any number of additional dispatches
return logicMiddleware.whenComplete(() => { // returns promise
  return store.getState(); // can serialize store, loading was done
});
  • logicMiddleware.monitor$ - observable for monitoring the internal operations inside all of your logic which is useful for debugging, testing, and for developing developer tools. More details in the advanced part of the API docs.

Migration instructions

  • You can check that your createLogicMiddleware, addLogic, and replaceLogic don't try to add the same logic refs multiple times or just check for an error when you run your tests. It will indicate which logic instances are duplicates. If you really do need duplicates then make a clone with Object.assign or similar.
  • If you are using { allowMore: true } for multiple dispatching, it is recommended to switch to the more intuitive approach using the additional done cb. The old way will likely continue to work since it is also used internally, but it is deprecated and you should change to the new style. Migrating involves taking out the { allowMore: true} and adding a call to the done cb when you are finished.
// since done is included in signature, multi-dispatch mode is enabled
// sets the default for processOptions.dispatchMultiple = true
process({ getState, action }, dispatch, done) {
  dispatch(foo);
  dispatch(bar); // dispatch any number of times
  done(); // when done dispatching
}
  • If you are using processOptions.dispatchReturn = true to dispatch the return obj, resolved promise or observable, then simply by omitting the dispatch from your process fn you will set the default dispatchReturn to true. Thus you don't have to specifically set dispatchReturn to true. It is fine to leave the code in but it is unnecessary as long as your fn signature omits the dispatch.
processOptions: {
  successType: FOO_SUCCESS, // optionally use this success action type/creator
  failType: FOO_FAILED // optionally use this fail action type/creator
},

// simply by omitting dispatch, we set the default for dispatchReturn to true
process({ getState, action }) {
  return objOrPromiseOrObservable; // returned or resolved value(s) will be dispatched
}