MobX-State-Tree Prebuilt Middlewares
raw JSON →mst-middlewares provides a collection of prebuilt middlewares for MobX-State-Tree (MST), primarily serving as examples and starting points for developers to create their own custom MST middlewares. Originally part of the `mobx-state-tree` monorepo, it was extracted into its own package to keep the core MST library small. The package is currently at version 6.1.0 and appears to have a release cadence driven by contributions and fixes, with a recent major bump to v6.0.0. Key differentiators include its direct lineage from the official MST repository, offering basic but functional examples like action logging and transactional rollbacks, and encouraging direct modification or copy-pasting of its source for specific project needs rather than relying on them as fully-fledged, heavily-supported features. Developers are encouraged to read the source code to understand how to implement custom middleware for MST's event system.
Common errors
error TypeError: Cannot read properties of undefined (reading 'addMiddleware') ↓
mobx-state-tree is installed (npm install mobx-state-tree or yarn add mobx-state-tree) and that addMiddleware or decorate are being called on a valid MST model instance created with types.model.create(). error SyntaxError: Cannot use import statement outside a module ↓
"type": "module" in package.json and adjust file extensions to .js or .mjs) or use a transpiler like Babel or TypeScript to convert ESM imports to CJS require statements during build. Modern Node.js versions support ESM directly when "type": "module" is set. Warnings
breaking Version 6.0.0 included a fix where `recorder.undo()` actions no longer register as an `UndoState` in the middleware. This might affect custom middleware logic that relies on inspecting the type of state produced by `recorder.undo()` operations. ↓
gotcha The provided middlewares are explicitly described as examples and are supported on a 'best effort' basis. They are not intended as fully robust, production-ready solutions for all use cases. ↓
gotcha The package originated from an undo of the MobX-State-Tree monorepo setup. This implies a historical context where these middlewares were internal examples, and their design reflects that, prioritizing clarity and demonstration over extreme optimization or comprehensive feature sets. ↓
Install
npm install mst-middlewares yarn add mst-middlewares pnpm add mst-middlewares Imports
- simpleActionLogger wrong
const simpleActionLogger = require('mst-middlewares').simpleActionLogger;correctimport { simpleActionLogger } from 'mst-middlewares'; - actionLogger wrong
import actionLogger from 'mst-middlewares/actionLogger';correctimport { actionLogger } from 'mst-middlewares'; - atomic wrong
const atomic = require('mst-middlewares');correctimport { atomic } from 'mst-middlewares';
Quickstart
import { types, addMiddleware, flow } from 'mobx-state-tree';
import { atomic } from 'mst-middlewares';
const delay = (ms: number) => new Promise(res => setTimeout(res, ms));
const TestModel = types
.model({
z: types.number,
})
.actions((self) => {
// Example of adding middleware directly
addMiddleware(self, atomic);
return {
inc: flow(function* (x: number) {
console.log(`Initial z: ${self.z}`);
yield delay(2);
self.z += x;
console.log(`z after first increment: ${self.z}`);
yield delay(2);
self.z += x;
console.log(`z after second increment: ${self.z}`);
throw new Error("Oops, something went wrong!");
}),
};
});
const m = TestModel.create({ z: 1 });
m.inc(3).catch((error: Error) => {
console.error(`Caught error: ${error.message}`);
console.log(`z after failed action (should be rolled back): ${m.z}`); // Expected: 1
});