When to use computed/observables in mobx
For anyone wondering how to use Computed in Functional Components.
You have to combine useMemo()
from react and computed()
from mobx:
TypeScript
import {useMemo} from 'react';
import {computed, IComputedValueOptions} from 'mobx';
// changes to "options" argument are ignored
export default function useComputed<T>(func: () => T, options?: IComputedValueOptions<T>, deps?: DependencyList)
{
return useMemo(() => computed(func, options), deps ?? []).get();
}
JavaScript
import {useMemo} from 'react';
import {computed} from 'mobx';
// changes to "options" argument are ignored
export default function useComputed(func, options)
{
return useMemo(() => computed(func, options), deps ?? []).get();
}
Example
export default observer(function MyComponent()
{
const sum = useComputed(() => observableA.myValue + observableB.myValue);
return <div>{sum}</div>
})
Props should be in dependencies
export default observer(function MyComponent({observableA, observableB})
{
const sum = useComputed(() => observableA.myValue + observableB.myValue, null, [observableA, observableB]);
return <div>{sum}</div>
})
If you don't put props in deps then computed()
will continue using old props and it will never update.
Don't forget to wrap your components with observer()
or it wont react to changes!
In principle @computed
is simple a directive that tells MobX: "this value could be cached until any of the observables that is used changes". So in fact they can always be left out, it will just mean that your app will recompute more, but it doesn't alter the results.
So if you are missing @computed
on the function that is in principle not a problem in most cases. If it is, you can use createTransformer
which takes a one-argument function and builds a (self cleaning) memoization cache of computed values. But it is a little bit more involved, so actually your solution to introduce a computed property in your ClientDetailsView
is nicer. I would indeed recommend doing that as long as you have a nice place to put that computed property (the component that needs it in this case)