mobx-react-lite
Advanced tools
Comparing version 2.0.0-alpha.0 to 2.0.0-alpha.1
@@ -226,2 +226,9 @@ (function (global, factory) { | ||
} | ||
function isPlainObject(value) { | ||
if (!value || typeof value !== "object") { | ||
return false; | ||
} | ||
var proto = Object.getPrototypeOf(value); | ||
return !proto || proto === Object.prototype; | ||
} | ||
@@ -395,8 +402,31 @@ var EMPTY_OBJECT = {}; | ||
function useAsObservableSource(current) { | ||
var _a = __read(react.useState(function () { return mobx.observable(current, {}, { deep: false }); }), 1), res = _a[0]; | ||
Object.assign(res, current); | ||
return res; | ||
} | ||
function useLocalStore(initializer) { | ||
return react.useState(function () { | ||
var store = mobx.observable(initializer()); | ||
if (isPlainObject(store)) { | ||
Object.keys(store).forEach(function (key) { | ||
var value = store[key]; | ||
if (typeof value === "function") { | ||
store[key] = mobx.action(value.bind(store)); | ||
} | ||
}); | ||
} | ||
return store; | ||
})[0]; | ||
} | ||
exports.Observer = ObserverComponent; | ||
exports.isUsingStaticRendering = isUsingStaticRendering; | ||
exports.observer = observer; | ||
exports.useAsObservableSource = useAsObservableSource; | ||
exports.useComputed = useComputed; | ||
exports.useDisposable = useDisposable; | ||
exports.useForceUpdate = useForceUpdate; | ||
exports.useLocalStore = useLocalStore; | ||
exports.useObservable = useObservable; | ||
@@ -403,0 +433,0 @@ exports.useObserver = useObserver; |
@@ -1,2 +0,2 @@ | ||
import { spy, observable, computed, getDependencyTree, Reaction } from 'mobx'; | ||
import { spy, observable, computed, getDependencyTree, Reaction, action } from 'mobx'; | ||
import { useState, useRef, useMemo, useEffect, useCallback, useDebugValue, memo, forwardRef } from 'react'; | ||
@@ -223,2 +223,9 @@ | ||
} | ||
function isPlainObject(value) { | ||
if (!value || typeof value !== "object") { | ||
return false; | ||
} | ||
var proto = Object.getPrototypeOf(value); | ||
return !proto || proto === Object.prototype; | ||
} | ||
@@ -392,2 +399,23 @@ var EMPTY_OBJECT = {}; | ||
export { ObserverComponent as Observer, isUsingStaticRendering, observer, useComputed, useDisposable, useForceUpdate, useObservable, useObserver, useStaticRendering }; | ||
function useAsObservableSource(current) { | ||
var _a = __read(useState(function () { return observable(current, {}, { deep: false }); }), 1), res = _a[0]; | ||
Object.assign(res, current); | ||
return res; | ||
} | ||
function useLocalStore(initializer) { | ||
return useState(function () { | ||
var store = observable(initializer()); | ||
if (isPlainObject(store)) { | ||
Object.keys(store).forEach(function (key) { | ||
var value = store[key]; | ||
if (typeof value === "function") { | ||
store[key] = action(value.bind(store)); | ||
} | ||
}); | ||
} | ||
return store; | ||
})[0]; | ||
} | ||
export { ObserverComponent as Observer, isUsingStaticRendering, observer, useAsObservableSource, useComputed, useDisposable, useForceUpdate, useLocalStore, useObservable, useObserver, useStaticRendering }; |
@@ -10,1 +10,3 @@ import "./assertEnvironment"; | ||
export { useForceUpdate } from "./utils"; | ||
export { useAsObservableSource } from "./useAsObservableSource"; | ||
export { useLocalStore } from "./useLocalStore"; |
@@ -226,2 +226,9 @@ (function (global, factory) { | ||
} | ||
function isPlainObject(value) { | ||
if (!value || typeof value !== "object") { | ||
return false; | ||
} | ||
var proto = Object.getPrototypeOf(value); | ||
return !proto || proto === Object.prototype; | ||
} | ||
@@ -395,8 +402,31 @@ var EMPTY_OBJECT = {}; | ||
function useAsObservableSource(current) { | ||
var _a = __read(react.useState(function () { return mobx.observable(current, {}, { deep: false }); }), 1), res = _a[0]; | ||
Object.assign(res, current); | ||
return res; | ||
} | ||
function useLocalStore(initializer) { | ||
return react.useState(function () { | ||
var store = mobx.observable(initializer()); | ||
if (isPlainObject(store)) { | ||
Object.keys(store).forEach(function (key) { | ||
var value = store[key]; | ||
if (typeof value === "function") { | ||
store[key] = mobx.action(value.bind(store)); | ||
} | ||
}); | ||
} | ||
return store; | ||
})[0]; | ||
} | ||
exports.Observer = ObserverComponent; | ||
exports.isUsingStaticRendering = isUsingStaticRendering; | ||
exports.observer = observer; | ||
exports.useAsObservableSource = useAsObservableSource; | ||
exports.useComputed = useComputed; | ||
exports.useDisposable = useDisposable; | ||
exports.useForceUpdate = useForceUpdate; | ||
exports.useLocalStore = useLocalStore; | ||
exports.useObservable = useObservable; | ||
@@ -403,0 +433,0 @@ exports.useObserver = useObserver; |
@@ -1,1 +0,1 @@ | ||
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("mobx"),require("react")):"function"==typeof define&&define.amd?define(["exports","mobx","react"],r):r((e=e||self).mobxReact={},e.mobx,e.React)}(this,function(e,r,n){"use strict";if(!n.useState)throw new Error("mobx-react-lite requires React with Hooks support");if(!r.spy)throw new Error("mobx-react-lite requires mobx at least version 4 to be available");var t=function(){};var o=!1;function u(){return o}var i=function(){return(i=Object.assign||function(e){for(var r,n=1,t=arguments.length;n<t;n++)for(var o in r=arguments[n])Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o]);return e}).apply(this,arguments)};function c(e){return r.getDependencyTree(e)}var a,f=1e4,l=1e4,s=new Set;function d(){void 0===a&&(a=setTimeout(p,l))}function p(){var e,r;a=void 0;var n=Date.now();try{for(var t=function(e){var r="function"==typeof Symbol&&e[Symbol.iterator],n=0;return r?r.call(e):{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}}(s),o=t.next();!o.done;o=t.next()){var u=o.value,i=u.current;i&&n>=i.cleanAt&&(i.reaction.dispose(),u.current=null,s.delete(u))}}catch(r){e={error:r}}finally{try{o&&!o.done&&(r=t.return)&&r.call(t)}finally{if(e)throw e.error}}s.size>0&&d()}function v(){var e=function(e,r){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var t,o,u=n.call(e),i=[];try{for(;(void 0===r||r-- >0)&&!(t=u.next()).done;)i.push(t.value)}catch(e){o={error:e}}finally{try{t&&!t.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}return i}(n.useState(0),2)[1];return n.useCallback(function(){e(function(e){return e+1})},[])}var y={};function b(e){return"observer"+e}function m(e,t,o){if(void 0===t&&(t="observed"),void 0===o&&(o=y),u())return e();var i,a=(o.useForceUpdate||v)(),l=n.useRef(null);if(!l.current){var p=new r.Reaction(b(t),function(){m.mounted?a():(p.dispose(),l.current=null)}),m=function(e){return{cleanAt:Date.now()+f,reaction:e}}(p);l.current=m,i=l,s.add(i),d()}var h,w,x=l.current.reaction;if(n.useDebugValue(x,c),n.useEffect(function(){var e;return e=l,s.delete(e),l.current?l.current.mounted=!0:(l.current={reaction:new r.Reaction(b(t),function(){a()}),cleanAt:1/0},a()),function(){return l.current.reaction.dispose()}},[]),x.track(function(){try{h=e()}catch(e){w=e}}),w)throw w;return h}var h={$$typeof:!0,render:!0,compare:!0,type:!0};function w(e){var r=e.children,n=e.render,t=r||n;return"function"!=typeof t?null:m(t)}function x(e,r,n,t,o){var u="children"===r?"render":"children",i="function"==typeof e[r],c="function"==typeof e[u];return i&&c?new Error("MobX Observer: Do not use children and render in the same time in`"+n):i||c?null:new Error("Invalid prop `"+o+"` of type `"+typeof e[r]+"` supplied to `"+n+"`, expected `function`.")}w.propTypes={children:x,render:x},w.displayName="Observer",e.Observer=w,e.isUsingStaticRendering=u,e.observer=function(e,r){if(u())return e;var t,o,c,a=i({forwardRef:!1},r),f=e.displayName||e.name,l=function(r,n){return m(function(){return e(r,n)},f)};return l.displayName=f,t=a.forwardRef?n.memo(n.forwardRef(l)):n.memo(l),o=e,c=t,Object.keys(o).forEach(function(e){o.hasOwnProperty(e)&&!h[e]&&Object.defineProperty(c,e,Object.getOwnPropertyDescriptor(o,e))}),t.displayName=f,t},e.useComputed=function(e,t){return void 0===t&&(t=[]),n.useMemo(function(){return r.computed(e)},t).get()},e.useDisposable=function(e,r){void 0===r&&(r=[]);var o=n.useRef(null),u=n.useRef(!1);function i(r){if(u.current)return t;if(!o.current){var n=e();if("function"!=typeof n){var i=new Error("generated disposer must be a function");return console.error(i),t}o.current=n}return function(){o.current&&(o.current(),o.current=null),r&&(u.current=!0)}}return n.useEffect(function(){return i(!1)},r),i(!0)},e.useForceUpdate=v,e.useObservable=function(e){var t=n.useRef(null);return t.current||(t.current=r.observable(e)),t.current},e.useObserver=m,e.useStaticRendering=function(e){o=e},Object.defineProperty(e,"__esModule",{value:!0})}); | ||
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?r(exports,require("mobx"),require("react")):"function"==typeof define&&define.amd?define(["exports","mobx","react"],r):r((e=e||self).mobxReact={},e.mobx,e.React)}(this,function(e,r,n){"use strict";if(!n.useState)throw new Error("mobx-react-lite requires React with Hooks support");if(!r.spy)throw new Error("mobx-react-lite requires mobx at least version 4 to be available");var t=function(){};var o=!1;function u(){return o}var c=function(){return(c=Object.assign||function(e){for(var r,n=1,t=arguments.length;n<t;n++)for(var o in r=arguments[n])Object.prototype.hasOwnProperty.call(r,o)&&(e[o]=r[o]);return e}).apply(this,arguments)};function i(e,r){var n="function"==typeof Symbol&&e[Symbol.iterator];if(!n)return e;var t,o,u=n.call(e),c=[];try{for(;(void 0===r||r-- >0)&&!(t=u.next()).done;)c.push(t.value)}catch(e){o={error:e}}finally{try{t&&!t.done&&(n=u.return)&&n.call(u)}finally{if(o)throw o.error}}return c}function a(e){return r.getDependencyTree(e)}var f,s=1e4,l=1e4,d=new Set;function p(){void 0===f&&(f=setTimeout(v,l))}function v(){var e,r;f=void 0;var n=Date.now();try{for(var t=function(e){var r="function"==typeof Symbol&&e[Symbol.iterator],n=0;return r?r.call(e):{next:function(){return e&&n>=e.length&&(e=void 0),{value:e&&e[n++],done:!e}}}}(d),o=t.next();!o.done;o=t.next()){var u=o.value,c=u.current;c&&n>=c.cleanAt&&(c.reaction.dispose(),u.current=null,d.delete(u))}}catch(r){e={error:r}}finally{try{o&&!o.done&&(r=t.return)&&r.call(t)}finally{if(e)throw e.error}}d.size>0&&p()}function b(){var e=i(n.useState(0),2)[1];return n.useCallback(function(){e(function(e){return e+1})},[])}var y={};function m(e){return"observer"+e}function h(e,t,o){if(void 0===t&&(t="observed"),void 0===o&&(o=y),u())return e();var c,i=(o.useForceUpdate||b)(),f=n.useRef(null);if(!f.current){var l=new r.Reaction(m(t),function(){v.mounted?i():(l.dispose(),f.current=null)}),v=function(e){return{cleanAt:Date.now()+s,reaction:e}}(l);f.current=v,c=f,d.add(c),p()}var h,w,O=f.current.reaction;if(n.useDebugValue(O,a),n.useEffect(function(){var e;return e=f,d.delete(e),f.current?f.current.mounted=!0:(f.current={reaction:new r.Reaction(m(t),function(){i()}),cleanAt:1/0},i()),function(){return f.current.reaction.dispose()}},[]),O.track(function(){try{h=e()}catch(e){w=e}}),w)throw w;return h}var w={$$typeof:!0,render:!0,compare:!0,type:!0};function O(e){var r=e.children,n=e.render,t=r||n;return"function"!=typeof t?null:h(t)}function x(e,r,n,t,o){var u="children"===r?"render":"children",c="function"==typeof e[r],i="function"==typeof e[u];return c&&i?new Error("MobX Observer: Do not use children and render in the same time in`"+n):c||i?null:new Error("Invalid prop `"+o+"` of type `"+typeof e[r]+"` supplied to `"+n+"`, expected `function`.")}O.propTypes={children:x,render:x},O.displayName="Observer",e.Observer=O,e.isUsingStaticRendering=u,e.observer=function(e,r){if(u())return e;var t,o,i,a=c({forwardRef:!1},r),f=e.displayName||e.name,s=function(r,n){return h(function(){return e(r,n)},f)};return s.displayName=f,t=a.forwardRef?n.memo(n.forwardRef(s)):n.memo(s),o=e,i=t,Object.keys(o).forEach(function(e){o.hasOwnProperty(e)&&!w[e]&&Object.defineProperty(i,e,Object.getOwnPropertyDescriptor(o,e))}),t.displayName=f,t},e.useAsObservableSource=function(e){var t=i(n.useState(function(){return r.observable(e,{},{deep:!1})}),1)[0];return Object.assign(t,e),t},e.useComputed=function(e,t){return void 0===t&&(t=[]),n.useMemo(function(){return r.computed(e)},t).get()},e.useDisposable=function(e,r){void 0===r&&(r=[]);var o=n.useRef(null),u=n.useRef(!1);function c(r){if(u.current)return t;if(!o.current){var n=e();if("function"!=typeof n){var c=new Error("generated disposer must be a function");return console.error(c),t}o.current=n}return function(){o.current&&(o.current(),o.current=null),r&&(u.current=!0)}}return n.useEffect(function(){return c(!1)},r),c(!0)},e.useForceUpdate=b,e.useLocalStore=function(e){return n.useState(function(){var n=r.observable(e());return function(e){if(!e||"object"!=typeof e)return!1;var r=Object.getPrototypeOf(e);return!r||r===Object.prototype}(n)&&Object.keys(n).forEach(function(e){var t=n[e];"function"==typeof t&&(n[e]=r.action(t.bind(n)))}),n})[0]},e.useObservable=function(e){var t=n.useRef(null);return t.current||(t.current=r.observable(e)),t.current},e.useObserver=h,e.useStaticRendering=function(e){o=e},Object.defineProperty(e,"__esModule",{value:!0})}); |
@@ -1,2 +0,2 @@ | ||
import { spy, observable, computed, getDependencyTree, Reaction } from 'mobx'; | ||
import { spy, observable, computed, getDependencyTree, Reaction, action } from 'mobx'; | ||
import { useState, useRef, useMemo, useEffect, useCallback, useDebugValue, memo, forwardRef } from 'react'; | ||
@@ -223,2 +223,9 @@ | ||
} | ||
function isPlainObject(value) { | ||
if (!value || typeof value !== "object") { | ||
return false; | ||
} | ||
var proto = Object.getPrototypeOf(value); | ||
return !proto || proto === Object.prototype; | ||
} | ||
@@ -392,2 +399,23 @@ var EMPTY_OBJECT = {}; | ||
export { ObserverComponent as Observer, isUsingStaticRendering, observer, useComputed, useDisposable, useForceUpdate, useObservable, useObserver, useStaticRendering }; | ||
function useAsObservableSource(current) { | ||
var _a = __read(useState(function () { return observable(current, {}, { deep: false }); }), 1), res = _a[0]; | ||
Object.assign(res, current); | ||
return res; | ||
} | ||
function useLocalStore(initializer) { | ||
return useState(function () { | ||
var store = observable(initializer()); | ||
if (isPlainObject(store)) { | ||
Object.keys(store).forEach(function (key) { | ||
var value = store[key]; | ||
if (typeof value === "function") { | ||
store[key] = action(value.bind(store)); | ||
} | ||
}); | ||
} | ||
return store; | ||
})[0]; | ||
} | ||
export { ObserverComponent as Observer, isUsingStaticRendering, observer, useAsObservableSource, useComputed, useDisposable, useForceUpdate, useLocalStore, useObservable, useObserver, useStaticRendering }; |
@@ -227,2 +227,9 @@ 'use strict'; | ||
} | ||
function isPlainObject(value) { | ||
if (!value || typeof value !== "object") { | ||
return false; | ||
} | ||
var proto = Object.getPrototypeOf(value); | ||
return !proto || proto === Object.prototype; | ||
} | ||
@@ -396,10 +403,33 @@ var EMPTY_OBJECT = {}; | ||
function useAsObservableSource(current) { | ||
var _a = __read(react.useState(function () { return mobx.observable(current, {}, { deep: false }); }), 1), res = _a[0]; | ||
Object.assign(res, current); | ||
return res; | ||
} | ||
function useLocalStore(initializer) { | ||
return react.useState(function () { | ||
var store = mobx.observable(initializer()); | ||
if (isPlainObject(store)) { | ||
Object.keys(store).forEach(function (key) { | ||
var value = store[key]; | ||
if (typeof value === "function") { | ||
store[key] = mobx.action(value.bind(store)); | ||
} | ||
}); | ||
} | ||
return store; | ||
})[0]; | ||
} | ||
exports.Observer = ObserverComponent; | ||
exports.isUsingStaticRendering = isUsingStaticRendering; | ||
exports.observer = observer; | ||
exports.useAsObservableSource = useAsObservableSource; | ||
exports.useComputed = useComputed; | ||
exports.useDisposable = useDisposable; | ||
exports.useForceUpdate = useForceUpdate; | ||
exports.useLocalStore = useLocalStore; | ||
exports.useObservable = useObservable; | ||
exports.useObserver = useObserver; | ||
exports.useStaticRendering = useStaticRendering; |
export declare function useForceUpdate(): () => void; | ||
export declare function isPlainObject(value: any): boolean; |
{ | ||
"name": "mobx-react-lite", | ||
"version": "2.0.0-alpha.0", | ||
"version": "2.0.0-alpha.1", | ||
"description": "Lightweight React bindings for MobX based on React 16.8 and Hooks", | ||
@@ -52,3 +52,5 @@ "main": "dist/index.js", | ||
"react-dom": "16.8.6", | ||
"react-test-renderer": "16.8.6", | ||
"react-testing-library": "7.0.0", | ||
"react-hooks-testing-library": "0.5.0", | ||
"rimraf": "2.6.3", | ||
@@ -55,0 +57,0 @@ "rollup": "1.10.1", |
167
README.md
@@ -17,12 +17,15 @@ # mobx-react-lite <!-- omit in toc --> | ||
- [API documentation](#api-documentation) | ||
- [`<Observer/>`](#observer) | ||
- [`observer<P>(baseComponent: FunctionComponent<P>, options?: IObserverOptions): FunctionComponent<P>`](#observerpbasecomponent-functioncomponentp-options-iobserveroptions-functioncomponentp) | ||
- [`useObserver<T>(fn: () => T, baseComponentName = "observed", options?: IUseObserverOptions): T`](#useobservertfn---t-basecomponentname--%22observed%22-options-iuseobserveroptions-t) | ||
- [`useObservable<T>(initialValue: T): T`](#useobservabletinitialvalue-t-t) | ||
- [Lazy initialization](#lazy-initialization) | ||
- [`useComputed(func: () => T, inputs: ReadonlyArray<any> = []): T`](#usecomputedfunc---t-inputs-readonlyarrayany---t) | ||
- [`useDisposable<D extends TDisposable>(disposerGenerator: () => D, inputs: ReadonlyArray<any> = []): D`](#usedisposabled-extends-tdisposabledisposergenerator---d-inputs-readonlyarrayany---d) | ||
- [Server Side Rendering with `useStaticRendering`](#server-side-rendering-with-usestaticrendering) | ||
- [Why no Provider/inject?](#why-no-providerinject) | ||
- [API documentation](#api-documentation) | ||
- [`<Observer/>`](#observer) | ||
- [`observer<P>(baseComponent: FunctionComponent<P>, options?: IObserverOptions): FunctionComponent<P>`](#observerpbasecomponent-functioncomponentp-options-iobserveroptions-functioncomponentp) | ||
- [`useObserver<T>(fn: () => T, baseComponentName = "observed", options?: IUseObserverOptions): T`](#useobservertfn---t-basecomponentname--%22observed%22-options-iuseobserveroptions-t) | ||
- [`useLocalStore<T>(initializer: () => T): T`](#uselocalstoretinitializer---t-t) | ||
- [`useAsObservableSource<T>(state: T): T`](#useasobservablesourcetstate-t-t) | ||
- [(deprecated) `useObservable<T>(initialValue: T): T`](#useobservabletinitialvalue-t-t) | ||
- [Lazy initialization](#lazy-initialization) | ||
- [(deprecated) `useComputed(func: () => T, inputs: ReadonlyArray<any> = []): T`](#usecomputedfunc---t-inputs-readonlyarrayany---t) | ||
- [(deprecated) `useDisposable<D extends TDisposable>(disposerGenerator: () => D, inputs: ReadonlyArray<any> = []): D`](#usedisposabled-extends-tdisposabledisposergenerator---d-inputs-readonlyarrayany---d) | ||
- [Creating MobX reactions inside hook components](#creating-mobx-reactions-inside-hook-components) | ||
- [Server Side Rendering with `useStaticRendering`](#server-side-rendering-with-usestaticrendering) | ||
- [Why no Provider/inject?](#why-no-providerinject) | ||
@@ -146,8 +149,88 @@ ## API documentation | ||
### `useLocalStore<T>(initializer: () => T): T` | ||
`useLocalStore` creates a local, observable store that is initialized once, and can be used throughout the life-cycle of the component. Use it if you want to use mobx-powered, local store. | ||
For simple cases it is recommended to use `React.setState`, but if your component requires complex view models, consider creating a local mobx store by using this hook. | ||
If the returned value is a plain object, it will be automatically be passed through `observable`, turning fields into observable properties, and `get` based property accessors in computed values, and functions in bound actions. | ||
If new class instances are returned from the initializer, they will be kept as is. Quick example: | ||
```typescript | ||
function Counter() { | ||
const store = useLocalStore(() => ({ | ||
count: 0, | ||
inc() { | ||
this.count += 1 | ||
} | ||
})) | ||
return useObserver(() => ( | ||
<div> | ||
Count: {store.count} | ||
<button onClick={store.inc}>Increment</button> | ||
</div> | ||
)) | ||
} | ||
``` | ||
It is important to realize that the store is created only once! It is not possible to specify dependencies to force re-creation, _nor should you directly be referring to props for the initializer function_, as changes in those won't propagate. | ||
Instead, if your store needs to refer to props (or `useState` based local state), the `useLocalStore` should be combined with the `useAsObservableSource` hook, see below. | ||
### `useAsObservableSource<T>(state: T): T` | ||
The `useAsObservableSource` hook can be used to turn any set of values into an observable object that has a stable reference (the same object is returned every time from the hook). | ||
The goal of this hook is to trap React primitives such as props or state into a local, observable object | ||
so that the `store` initializer can safely refer to it, and get notified if any of the values change. | ||
Example: | ||
```typescript | ||
function Counter({ multiplier }) { | ||
const observableProps = useAsObservableSource({ multiplier }) | ||
const store = useLocalStore(() => ({ | ||
count: 0, | ||
get multiplied() { | ||
return observableProps.multiplier * this.count | ||
}, | ||
inc() { | ||
this.count += 1 | ||
} | ||
})) | ||
return ( | ||
<Observer> | ||
{() => ( | ||
<div> | ||
Multiplied count: {store.multiplied} | ||
<button onClick={store.inc}>Increment</button> | ||
</div> | ||
)} | ||
</Observer> | ||
) | ||
} | ||
``` | ||
In the above example, any change to `multiplier` prop will show up in the `observableProps` observable object, and be picked up by the `store`. | ||
Warning: _the return value of `useAsObservableSource` should never be deconstructed! So, don't write: `const {multiplier} = useAsObservableSource({ multiplier })`!_ | ||
The value passed to `useAsObservableSource` should always be an object, and is made only shallowly observable. | ||
The object returned by `useAsObservableSource`, although observable, should be considered read-only for all practical purposes. | ||
Use `useLocalStore` to create local, observable, mutable, state. | ||
Tip: for optimal performance it is recommend to not use `useAsObservableSource` together on the same component as `useObserver` (or `observer`), as it might trigger double renderings. Instead, use `<Observer>`. | ||
# Notice of deprecation | ||
We are considering deprecation and removal of following utilities from the package. Come join the discussion: https://github.com/mobxjs/mobx-react-lite/issues/94 | ||
We will be deprecating following utilities from the package in the next major version. See [the discussion](https://github.com/mobxjs/mobx-react-lite/issues/94) and [the relevant PR](https://github.com/mobxjs/mobx-react-lite/pull/130) for details. | ||
---- | ||
### `useObservable<T>(initialValue: T): T` | ||
_Deprecated, will be removed in next major_ | ||
React hook that allows creating observable object within a component body and keeps track of it over renders. Gets all the benefits from [observable objects](https://mobx.js.org/refguide/object.html) including computed properties and methods. You can also use arrays, Map and Set. | ||
@@ -210,2 +293,4 @@ | ||
_Deprecated, will be removed in next major_ | ||
Another React hook that simplifies computational logic. It's just a tiny wrapper around [MobX computed](https://mobx.js.org/refguide/computed-decorator.html#-computed-expression-as-function) function that runs computation whenever observable values change. In conjuction with `observer` the component will rerender based on such a change. | ||
@@ -242,2 +327,4 @@ | ||
_Deprecated, will be removed in next major_ | ||
The disposable is any kind of function that returns another function to be called on a component unmount to clean up used resources. Use MobX related functions like [`reaction`](https://mobx.js.org/refguide/reaction.html), [`autorun`](https://mobx.js.org/refguide/autorun.html), [`when`](https://mobx.js.org/refguide/when.html), [`observe`](https://mobx.js.org/refguide/observe.html), or anything else that returns a disposer. | ||
@@ -273,2 +360,60 @@ Returns the generated disposer for early disposal. | ||
## Creating MobX reactions inside hook components | ||
If needed, it is possible to create MobX based side effects in hook based components using the standard APIs. For example: | ||
```typescript | ||
function Counter() { | ||
const store = useLocalStore(() => ({ | ||
count: 0, | ||
inc() { | ||
store.count += 1 | ||
} | ||
})) | ||
useEffect( | ||
() => | ||
autorun(() => { | ||
document.title = "Ticked: " + store.count | ||
}), | ||
[] | ||
) | ||
return /* etc */ | ||
} | ||
``` | ||
Note that the disposer function of `autorun` should be returned to `useEffect` so that the effect is cleaned up properly by React. | ||
Secondly, when using MobX based side effects, you typically don't want to re-create them after each rendering, so make sure to pass in an empty array `[]` as deps to `useEffect`. | ||
This will yield the same limitation as when using `useLocalStore`: changes to props used by the side-effect won't be picked up automatically, so don't refer to them directly. Instead, leverage `useAsObservableSource` again: | ||
```typescript | ||
function Counter({ prefix }) { | ||
const observableProps = useAsObservableSource({ prefix }) | ||
const store = useLocalStore(() => ({ | ||
count: 0, | ||
inc() { | ||
store.count += 1 | ||
} | ||
})) | ||
useEffect( | ||
() => | ||
autorun(() => { | ||
document.title = `${observableProps.prefix}: ${store.count}` | ||
}), | ||
[] | ||
) | ||
return useObserver(() => ( | ||
<div> | ||
Count: {store.count} | ||
<button onClick={store.inc}>Increment</button> | ||
</div> | ||
)) | ||
} | ||
``` | ||
## Server Side Rendering with `useStaticRendering` | ||
@@ -275,0 +420,0 @@ |
Sorry, the diff of this file is not supported yet
327023
25
2172
451
32