New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mobx-react-lite

Package Overview
Dependencies
Maintainers
1
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mobx-react-lite - npm Package Compare versions

Comparing version 1.4.0 to 1.4.1

16

dist/custom.js

@@ -284,3 +284,5 @@ (function (global, factory) {

var _a = __read(React__default.useState(function () { return mobx.observable(current, {}, { deep: false }); }), 1), res = _a[0];
Object.assign(res, current);
mobx.runInAction(function () {
Object.assign(res, current);
});
return res;

@@ -297,7 +299,9 @@ }

if (isPlainObject(local)) {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
mobx.runInAction(function () {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
});
});

@@ -304,0 +308,0 @@ }

@@ -1,2 +0,2 @@

import { spy, observable, computed, getDependencyTree, Reaction, transaction } from 'mobx';
import { spy, observable, computed, getDependencyTree, Reaction, runInAction, transaction } from 'mobx';
import React, { useState, useRef, useMemo, useEffect, useCallback, useDebugValue, memo, forwardRef } from 'react';

@@ -279,3 +279,5 @@

var _a = __read(React.useState(function () { return observable(current, {}, { deep: false }); }), 1), res = _a[0];
Object.assign(res, current);
runInAction(function () {
Object.assign(res, current);
});
return res;

@@ -292,7 +294,9 @@ }

if (isPlainObject(local)) {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
runInAction(function () {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
});
});

@@ -299,0 +303,0 @@ }

@@ -284,3 +284,5 @@ (function (global, factory) {

var _a = __read(React__default.useState(function () { return mobx.observable(current, {}, { deep: false }); }), 1), res = _a[0];
Object.assign(res, current);
mobx.runInAction(function () {
Object.assign(res, current);
});
return res;

@@ -297,7 +299,9 @@ }

if (isPlainObject(local)) {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
mobx.runInAction(function () {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
});
});

@@ -304,0 +308,0 @@ }

@@ -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).mobxReactLite={},e.mobx,e.React)}(this,function(e,r,n){"use strict";var t="default"in n?n.default:n;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 o=function(){};var u=!1;function i(){return u}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 f(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}function a(e){return e.current?r.getDependencyTree(e.current):"<unknown>"}var s=[];function l(){var e=f(n.useState(0),2)[1];return n.useCallback(function(){e(function(e){return e+1})},[])}var p={};function d(e,t,o){if(void 0===t&&(t="observed"),void 0===o&&(o=p),i())return e();var u=(o.useForceUpdate||l)(),c=n.useRef(null);c.current||(c.current=new r.Reaction("observer("+t+")",function(){u()}));var f,d,v=function(){c.current&&!c.current.isDisposed&&c.current.dispose()};if(n.useDebugValue(c,a),function(e){n.useEffect(function(){return e},s)}(function(){v()}),c.current.track(function(){try{f=e()}catch(e){d=e}}),d)throw v(),d;return f}var v={$$typeof:!0,render:!0,compare:!0,type:!0};function b(e){var r=e.children,n=e.render,t=r||n;return"function"!=typeof t?null:d(t)}function y(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`.")}function m(e,n){if(!n||void 0!==e){var o=f(t.useState(function(){return r.observable(e,{},{deep:!1})}),1)[0];return Object.assign(o,e),o}}b.propTypes={children:y,render:y},b.displayName="Observer",e.Observer=b,e.isUsingStaticRendering=i,e.observer=function(e,r){if(i())return e;var t,o,u,f=c({forwardRef:!1},r),a=e.displayName||e.name,s=function(r,n){return d(function(){return e(r,n)},a)};return s.displayName=a,t=f.forwardRef?n.memo(n.forwardRef(s)):n.memo(s),o=e,u=t,Object.keys(o).forEach(function(e){o.hasOwnProperty(e)&&!v[e]&&Object.defineProperty(u,e,Object.getOwnPropertyDescriptor(o,e))}),t.displayName=a,t},e.useAsObservableSource=function(e){return m(e,!1)},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 t=n.useRef(null),u=n.useRef(!1);function i(r){if(u.current)return o;if(!t.current){var n=e();if("function"!=typeof n){var i=new Error("generated disposer must be a function");return console.error(i),o}t.current=n}return function(){t.current&&(t.current(),t.current=null),r&&(u.current=!0)}}return n.useEffect(function(){return i(!1)},r),i(!0)},e.useForceUpdate=l,e.useLocalStore=function(e,n){var o=m(n,!0);return t.useState(function(){var n=r.observable(e(o));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,o,u=n[e];"function"==typeof u&&(n[e]=(t=u,o=n,function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];return r.transaction(function(){return t.apply(o,e)})}))}),n})[0]},e.useObservable=function(e){var t=n.useRef(null);return t.current||(t.current=r.observable(e)),t.current},e.useObserver=d,e.useStaticRendering=function(e){u=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).mobxReactLite={},e.mobx,e.React)}(this,function(e,r,n){"use strict";var t="default"in n?n.default:n;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 o=function(){};var u=!1;function i(){return u}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 f(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}function a(e){return e.current?r.getDependencyTree(e.current):"<unknown>"}var s=[];function l(){var e=f(n.useState(0),2)[1];return n.useCallback(function(){e(function(e){return e+1})},[])}var p={};function d(e,t,o){if(void 0===t&&(t="observed"),void 0===o&&(o=p),i())return e();var u=(o.useForceUpdate||l)(),c=n.useRef(null);c.current||(c.current=new r.Reaction("observer("+t+")",function(){u()}));var f,d,v=function(){c.current&&!c.current.isDisposed&&c.current.dispose()};if(n.useDebugValue(c,a),function(e){n.useEffect(function(){return e},s)}(function(){v()}),c.current.track(function(){try{f=e()}catch(e){d=e}}),d)throw v(),d;return f}var v={$$typeof:!0,render:!0,compare:!0,type:!0};function b(e){var r=e.children,n=e.render,t=r||n;return"function"!=typeof t?null:d(t)}function y(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`.")}function m(e,n){if(!n||void 0!==e){var o=f(t.useState(function(){return r.observable(e,{},{deep:!1})}),1)[0];return r.runInAction(function(){Object.assign(o,e)}),o}}b.propTypes={children:y,render:y},b.displayName="Observer",e.Observer=b,e.isUsingStaticRendering=i,e.observer=function(e,r){if(i())return e;var t,o,u,f=c({forwardRef:!1},r),a=e.displayName||e.name,s=function(r,n){return d(function(){return e(r,n)},a)};return s.displayName=a,t=f.forwardRef?n.memo(n.forwardRef(s)):n.memo(s),o=e,u=t,Object.keys(o).forEach(function(e){o.hasOwnProperty(e)&&!v[e]&&Object.defineProperty(u,e,Object.getOwnPropertyDescriptor(o,e))}),t.displayName=a,t},e.useAsObservableSource=function(e){return m(e,!1)},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 t=n.useRef(null),u=n.useRef(!1);function i(r){if(u.current)return o;if(!t.current){var n=e();if("function"!=typeof n){var i=new Error("generated disposer must be a function");return console.error(i),o}t.current=n}return function(){t.current&&(t.current(),t.current=null),r&&(u.current=!0)}}return n.useEffect(function(){return i(!1)},r),i(!0)},e.useForceUpdate=l,e.useLocalStore=function(e,n){var o=m(n,!0);return t.useState(function(){var n=r.observable(e(o));return function(e){if(!e||"object"!=typeof e)return!1;var r=Object.getPrototypeOf(e);return!r||r===Object.prototype}(n)&&r.runInAction(function(){Object.keys(n).forEach(function(e){var t,o,u=n[e];"function"==typeof u&&(n[e]=(t=u,o=n,function(){for(var e=[],n=0;n<arguments.length;n++)e[n]=arguments[n];return r.transaction(function(){return t.apply(o,e)})}))})}),n})[0]},e.useObservable=function(e){var t=n.useRef(null);return t.current||(t.current=r.observable(e)),t.current},e.useObserver=d,e.useStaticRendering=function(e){u=e},Object.defineProperty(e,"__esModule",{value:!0})});

@@ -1,2 +0,2 @@

import { spy, observable, computed, getDependencyTree, Reaction, transaction } from 'mobx';
import { spy, observable, computed, getDependencyTree, Reaction, runInAction, transaction } from 'mobx';
import React, { useState, useRef, useMemo, useEffect, useCallback, useDebugValue, memo, forwardRef } from 'react';

@@ -279,3 +279,5 @@

var _a = __read(React.useState(function () { return observable(current, {}, { deep: false }); }), 1), res = _a[0];
Object.assign(res, current);
runInAction(function () {
Object.assign(res, current);
});
return res;

@@ -292,7 +294,9 @@ }

if (isPlainObject(local)) {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
runInAction(function () {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
});
});

@@ -299,0 +303,0 @@ }

@@ -286,3 +286,5 @@ 'use strict';

var _a = __read(React__default.useState(function () { return mobx.observable(current, {}, { deep: false }); }), 1), res = _a[0];
Object.assign(res, current);
mobx.runInAction(function () {
Object.assign(res, current);
});
return res;

@@ -299,7 +301,9 @@ }

if (isPlainObject(local)) {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
mobx.runInAction(function () {
Object.keys(local).forEach(function (key) {
var value = local[key];
if (typeof value === "function") {
local[key] = wrapInTransaction(value, local);
}
});
});

@@ -306,0 +310,0 @@ }

{
"name": "mobx-react-lite",
"version": "1.4.0",
"version": "1.4.1",
"description": "Lightweight React bindings for MobX based on React 16.8 and Hooks",

@@ -31,3 +31,3 @@ "main": "dist/index.js",

},
"homepage": "https://mobxjs.github.io/mobx",
"homepage": "https://mobx-react.js.org",
"peerDependencies": {

@@ -38,32 +38,32 @@ "mobx": "^4.0.0 || ^5.0.0",

"devDependencies": {
"@types/jest": "24.0.13",
"@types/node": "12.0.2",
"@types/react": "16.8.18",
"@testing-library/react": "8.0.4",
"@testing-library/react-hooks": "1.0.4",
"@types/jest": "24.0.15",
"@types/node": "12.0.10",
"@types/react": "16.8.22",
"@types/react-dom": "16.8.4",
"coveralls": "3.0.3",
"husky": "2.3.0",
"coveralls": "3.0.4",
"husky": "2.5.0",
"jest": "24.8.0",
"jest-dom": "3.4.0",
"jest-dom": "3.5.0",
"jest-environment-jsdom": "24.8.0",
"jest-mock-console": "1.0.0",
"lint-staged": "8.1.7",
"lint-staged": "8.2.1",
"lodash": "4.17.11",
"mobx": "5.9.4",
"prettier": "1.17.1",
"mobx": "5.10.1",
"prettier": "1.18.2",
"react": "16.8.6",
"react-dom": "16.8.6",
"react-hooks-testing-library": "0.5.0",
"react-test-renderer": "16.8.6",
"react-testing-library": "7.0.1",
"rimraf": "2.6.3",
"rollup": "1.12.4",
"rollup-plugin-alias": "1.5.1",
"rollup": "1.16.2",
"rollup-plugin-alias": "1.5.2",
"rollup-plugin-commonjs": "10.0.0",
"rollup-plugin-filesize": "6.1.0",
"rollup-plugin-node-resolve": "5.0.0",
"rollup-plugin-filesize": "6.1.1",
"rollup-plugin-node-resolve": "5.1.0",
"rollup-plugin-replace": "2.2.0",
"rollup-plugin-terser": "5.0.0",
"rollup-plugin-typescript2": "0.21.1",
"rollup-plugin-typescript2": "0.21.2",
"ts-jest": "24.0.2",
"tslint": "5.16.0",
"tslint": "5.18.0",
"tslint-config-prettier": "1.18.0",

@@ -70,0 +70,0 @@ "typescript": "3.4.5"

@@ -11,3 +11,3 @@ # mobx-react-lite <!-- omit in toc -->

Class based components **are not supported** except using `<Observer>` directly in its `render` method. If you want to transition existing projects from classes to hooks (as most of us do), you can use this package alongside the [mobx-react](https://github.com/mobxjs/mobx-react) just fine. The only conflict point is about the `observer` HOC. Subscribe [to this issue](https://github.com/mobxjs/mobx-react/issues/640) for a proper migration guide.
Class based components **are not supported** except using `<Observer>` directly in class `render` method. If you want to transition existing projects from classes to hooks (as most of us do), you can use this package alongside the [mobx-react](https://github.com/mobxjs/mobx-react) just fine. The only conflict point is about the `observer` HOC. Subscribe [to this issue](https://github.com/mobxjs/mobx-react/issues/640) for a proper migration guide.

@@ -18,218 +18,45 @@ [![NPM](https://nodei.co/npm/mobx-react-lite.png)](https://www.npmjs.com/package/mobx-react-lite)

- [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)
## User Guide 👉 https://mobx-react.js.org
## API documentation
The site contains various examples and recipes for using MobX in React world. Feel free to contribute. The API reference of this package follows 👇.
### `<Observer/>`
## API reference ⚒
`Observer` is a React component, which applies observer to an anonymous region in your component.
It takes as children a single, argumentless function which should return exactly one React component.
The rendering in the function will be tracked and automatically re-rendered when needed.
This can come in handy when needing to pass render function to external components (for example the React Native listview), or if you want to observe only relevant parts of the output for a performance reasons.
> **`<Observer>{renderFn}</Observer>`** _([user guide](https://mobx-react.netlify.com/observer-component))_
```jsx
import { Observer, useObservable } from "mobx-react-lite"
> **`observer<P>(baseComponent: FunctionComponent<P>, options?: IObserverOptions): FunctionComponent<P>`** _([user guide](https://mobx-react.netlify.com/observer-hoc))_
function ObservePerson(props) {
const person = useObservable({ name: "John" })
return (
<div>
{person.name}
<Observer>{() => <div>{person.name}</div>}</Observer>
<button onClick={() => (person.name = "Mike")}>No! I am Mike</button>
</div>
)
```ts
interface IObserverOptions {
// Pass true to use React.forwardRef over the inner component. It's false by the default.
forwardRef?: boolean
}
```
[![Edit ObservePerson](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/jzj48v2xry?module=%2Fsrc%2FObservePerson.tsx)
> **`useObserver<T>(fn: () => T, baseComponentName = "observed", options?: IUseObserverOptions): T`** _([user guide](https://mobx-react.netlify.com/observer-hook))_
In case you are a fan of render props, you can use that instead of children. Be advised, that you cannot use both approaches at once, children have a precedence.
Example
```jsx
import { Observer, useObservable } from "mobx-react-lite"
function ObservePerson(props) {
const person = useObservable({ name: "John" })
return (
<div>
{person.name}
<Observer render={() => <div>{person.name}</div>} />
<button onClick={() => (person.name = "Mike")}>No! I am Mike</button>
</div>
)
```ts
interface IUseObserverOptions {
// optional custom hook that should make a component re-render (or not) upon changes
useForceUpdate: () => () => void
}
```
### `observer<P>(baseComponent: FunctionComponent<P>, options?: IObserverOptions): FunctionComponent<P>`
**`useLocalStore<T, S>(initializer: () => T, source?: S): T`** _([user guide](https://mobx-react.netlify.com/state-local))_
Function that converts a function component into a reactive component, which tracks which observables are used automatically re-renders the component when one of these values changes. Observables can be passed through props, accessed from context or created locally with `useObservable`.
**`useAsObservableSource<T>(source: T): T`** _([user guide](https://mobx-react.netlify.com/state-outsourcing))_
As for options, it is an optional object with the following optional properties:
## React Strict mode ☄
- `forwardRef`: pass `true` to use [`forwardRef`](https://reactjs.org/docs/forwarding-refs.html) over the inner component, pass `false` (the default) otherwise.
Feel free to try out `mobx-react-lite@next` which is based on latest 1.x, but contains experimental support for handling Concurrent mode in React properly.
```tsx
import { observer, useObservable } from "mobx-react-lite"
## Deprecation notice ⚠
const FriendlyComponent = observer(() => {
const friendNameRef = React.useRef()
const data = useObservable({
friends: [] as string[],
addFriend(favorite: boolean = false) {
if (favorite === true) {
data.friends.unshift(friendNameRef.current.value + " * ")
} else {
data.friends.push(friendNameRef.current.value)
}
friendNameRef.current.value = ""
},
get friendsCount() {
return data.friends.length
}
})
Following utilities are still available in the package, but they are deprecated and will be removed in the next major version (2.x). As such, they are not mentioned in the user guide and it's not recommend to continue using these.
return (
<div>
<b>Count of friends: {data.friendsCount} </b>
{data.friends.map(friend => (
<div>{friend}</div>
))}
<hr />
<input ref={friendNameRef} />
<button onClick={data.addFriend}>Add friend </button>
<button onClick={() => data.addFriend(true)}>Add favorite friend</button>
</div>
)
})
```
---
[![Edit FriendlyComponent](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/jzj48v2xry?module=%2Fsrc%2FFriendlyComponent.tsx)
### `useObserver<T>(fn: () => T, baseComponentName = "observed", options?: IUseObserverOptions): T`
Low level implementation used internally by `observer`.
It allows you to use an `observer` like behaviour, but still allowing you to optimize the component in any way you want (e.g. using `memo` with a custom `areEqual`, using `forwardRef`, etc.) and to declare exactly the part that is observed (the render phase). One good thing about this is that if any hook changes an observable for some reason then the component won't rerender twice unnecessarily.
The following optional parameters are available:
- `baseComponentName`: a string that will be used as part of the reaction name.
As for the options, the following are available:
- `useForceUpdate`: optional custom hook that should make a component re-render (or not) when changes are detected.
```tsx
import { memo } from "react"
import { useObserver, useObservable } from "mobx-react-lite"
const Person = memo(props => {
const person = useObservable({ name: "John" })
return useObserver(() => (
<div>
{person.name}
<button onClick={() => (person.name = "Mike")}>No! I am Mike</button>
</div>
))
})
```
### `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 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_
> **Use the `useLocalStore` instead** ([user guide](https://mobx-react.netlify.com/state-local))

@@ -293,3 +120,3 @@ 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.

_Deprecated, will be removed in next major_
> **Use the `useLocalStore` instead** ([user guide](https://mobx-react.netlify.com/state-local))

@@ -327,3 +154,3 @@ 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.

_Deprecated, will be removed in next major_
> **Use the `React.useEffect` instead** ([user guide](https://mobx-react.netlify.com/recipes-effects))

@@ -359,97 +186,1 @@ 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.

```
## 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`
When using server side rendering, the components are rendered only once.
Since components are never unmounted, `observer` components would in this case leak memory when being rendered server side.
To avoid leaking memory, call `useStaticRendering(true)` when using server side rendering which essentially disables observer.
```js
import { useStaticRendering } from "mobx-react-lite"
useStaticRendering(true)
```
This makes sure the component won't try to react to any future data changes.
## Why no Provider/inject?
Historically the Provider was useful because a lot of boilerplate was required due to experimental (but widely used) context. By introducing new [Context API](https://reactjs.org/docs/context.html) in React 16.3 it's fairly easy to do this.
```js
const StoreContext = React.createContext(createStore())
// a file with a component
function ConnectedComponent() {
// replacement for inject
const store = useContext(StoreContext)
}
```
If you need to create a store sometimes later, you can just render `StoreContext.Provider` somewhere in tree.
```js
const StoreContext = React.createContext()
function App({ children }) {
return <StoreContext.Provider value={createStore()}>{children}</StoreContext.Provider>
}
```

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc