What is mobx-utils?
The mobx-utils package provides a set of utility functions and classes to complement MobX, a state management library for JavaScript applications. These utilities help simplify common patterns and enhance the functionality of MobX.
What are mobx-utils's main functionalities?
fromPromise
The `fromPromise` utility converts a promise into an observable object, allowing you to easily track the state of asynchronous operations within MobX.
const { fromPromise } = require('mobx-utils');
const { observable } = require('mobx');
const fetchData = () => new Promise(resolve => setTimeout(() => resolve('data'), 1000));
const observablePromise = fromPromise(fetchData());
observablePromise.case({
pending: () => console.log('Loading...'),
fulfilled: value => console.log('Data:', value),
rejected: error => console.log('Error:', error)
});
lazyObservable
The `lazyObservable` utility creates an observable that only starts producing values when it is first observed. This is useful for deferring expensive computations or data fetching until necessary.
const { lazyObservable } = require('mobx-utils');
const lazyData = lazyObservable(sink => {
setTimeout(() => sink('Lazy data'), 1000);
});
lazyData.observe(newValue => console.log('New value:', newValue));
keepAlive
The `keepAlive` utility ensures that a computed value remains active and is not garbage collected, even if there are no observers. This can be useful for maintaining the state of certain computations.
const { keepAlive } = require('mobx-utils');
const { observable, computed } = require('mobx');
const data = observable.box(1);
const computedValue = computed(() => data.get() * 2);
keepAlive(computedValue);
console.log(computedValue.get()); // 2
data.set(2);
console.log(computedValue.get()); // 4
Other packages similar to mobx-utils
mobx-state-tree
MobX-State-Tree (MST) is a state management library built on top of MobX. It provides a structured way to manage state with a focus on immutability and snapshots. Unlike mobx-utils, which offers utility functions, MST provides a more opinionated and structured approach to state management.
redux
Redux is a popular state management library for JavaScript applications. It uses a single immutable state tree and actions to update the state. While Redux is more verbose and has a steeper learning curve compared to MobX and mobx-utils, it is widely adopted and has a large ecosystem of middleware and tools.
recoil
Recoil is a state management library for React applications developed by Facebook. It provides a more fine-grained approach to state management compared to MobX and mobx-utils, with a focus on performance and scalability. Recoil's API is designed to be simple and intuitive for React developers.
MobX-utils
Work in progress
Installation
NPM: npm install mobx-utils --save
CDN: https://npmcdn.com/mobx-utils/mobx-utils.umd.js
API
fromPromise
lib/from-promise.js:53-57
Parameters
promise
IThenable<T>initialValue
[T] (optional, default undefined
)modifier
[any] (optional, default IDENTITY
)
Returns IPromiseBasedObservable<T>
whenWithTimeout
lib/guarded-when.js:32-51
Like normal when
, except that this when
will automatically dispose if the condition isn't met within a certain amount of time.
Parameters
expr
action
timeout
[number] maximum amount when spends waiting before giving up (optional, default 10000
)onTimeout
[any] the ontimeout handler will be called if the condition wasn't met withing the given time (optional, default ()
)
Examples
test("expect store to load", t => {
const store = {
items: [],
loaded: false
}
fetchDataForStore((data) => {
store.items = data;
store.loaded = true;
})
whenWithTimeout(
() => store.loaded
() => t.end()
2000,
() => t.fail("expected store to load")
)
})
Returns IDisposer disposer function that can be used to cancel the when prematurely. Neither action or onTimeout will be fired if disposed
keepAlive
lib/keep-alive.js:35-40
MobX normally suspends any computed value that is not in use by any reaction,
and lazily re-evaluates the expression if needed outside a reaction while not in use.
keepAlive
marks a computed value as always in use, meaning that it will always fresh, but never disposed.
Parameters
computedValue
IComputedValue<any> created using the computed
function_1
_2
Examples
const number = observable(3)
const doubler = computed(() => number.get() * 2)
const stop = keepAlive(doubler)
stop()
Returns IDisposer stops this keep alive so that the computed value goes back to normal behavior
keepAlive
lib/keep-alive.js:35-40
MobX normally suspends any computed value that is not in use by any reaction,
and lazily re-evaluates the expression if needed outside a reaction while not in use.
keepAlive
marks a computed value as always in use, meaning that it will always fresh, but never disposed.
Parameters
target
Object an object that has a computed property, created by @computed
or extendObservable
property
string the name of the property to keep alive_1
_2
Examples
const obj = observable({
number: 3,
doubler: function() { return this.number * 2 }
})
const stop = keepAlive(obj, "doubler")
Returns IDisposer stops this keep alive so that the computed value goes back to normal behavior
fromResource
lib/from-resource.js:60-92
fromResource
creates an observable which current state can be inspected using .get()
,
and which can be kept in sync with some external datasource that can be subscribed to.
The created observable will only subscribe to the datasource if it is in use somewhere,
(un)subscribing when needed. To enable fromResource
to do that two callbacks need to be provided,
one to subscribe, and one to unsubscribe. The subscribe callback itself will receive a sink
callback, which can be used
to update the current state of the observable, allowing observes to react.
Whatever is passed to sink
will be returned by get()
. It is the get()
call itself which is being tracked,
so make sure that you don't dereference to early.
The following example code creates an observable that connects to a dbUserRecord
,
which comes from an imaginary database and notifies when it has changed.
Parameters
subscriber
unsubscriber
[IDisposer] (optional, default NOOP
)initialValue
[T] the data that will be returned by get()
until the sink
has emitted its first data (optional, default undefined
)
Examples
function createObservableUser(dbUserRecord) {
let currentSubscription;
return fromResource(
(sink) => {
sink(dbUserRecord.fields)
currentSubscription = dbUserRecord.onUpdated(() => {
sink(dbUserRecord.fields)
})
},
() => {
dbUserRecord.unsubscribe(currentSubscription)
},
dbUserRecord.fields
)
}
const myUserObservable = createObservableUser(myDatabaseConnector.query("name = 'Michel'"))
autorun(() => {
console.log(myUserObservable.get().displayName)
})
const userComponent = observer(({ user }) =>
<div>{user.get().displayName}</div>
)