UNPKG

8.94 kBMarkdownView Raw
1# mobx-react-lite
2
3[![CircleCI](https://circleci.com/gh/mobxjs/mobx-react-lite.svg?style=svg)](https://circleci.com/gh/mobxjs/mobx-react-lite)[![Coverage Status](https://coveralls.io/repos/github/mobxjs/mobx-react-lite/badge.svg)](https://coveralls.io/github/mobxjs/mobx-react-lite)[![NPM downloads](https://img.shields.io/npm/dm/mobx-react-lite.svg?style=flat)](https://npmjs.com/package/mobx-react-lite)[![Minzipped size](https://img.shields.io/bundlephobia/minzip/mobx-react-lite.svg)](https://bundlephobia.com/result?p=mobx-react-lite)
4
5[![TypeScript](https://badges.frapsoft.com/typescript/code/typescript.svg?v=101)](https://github.com/ellerbrock/typescript-badges/)[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
6
7[![Discuss on Github](https://img.shields.io/badge/discuss%20on-GitHub-orange)](https://github.com/mobxjs/mobx/discussions)
8[![View changelog](https://img.shields.io/badge/changelogs.xyz-Explore%20Changelog-brightgreen)](https://changelogs.xyz/mobx-react-lite)
9
10This is a lighter version of [mobx-react](https://github.com/mobxjs/mobx-react) which supports React **functional components only** and as such makes the library slightly faster and smaller (_only 1.5kB gzipped_). Note however that it is possible to use `<Observer>` inside the render of class components.
11Unlike `mobx-react`, it doesn't `Provider`/`inject`, as `useContext` can be used instead.
12
13## Compatibility table (major versions)
14
15| mobx | mobx-react-lite | Browser |
16| ---- | --------------- | ---------------------------------------------- |
17| 6 | 3 | Modern browsers (IE 11+ in compatibility mode) |
18| 5 | 2 | Modern browsers |
19| 4 | 2 | IE 11+, RN w/o Proxy support |
20
21`mobx-react-lite` requires React 16.8 or higher.
22
23## User Guide 👉 https://mobx.js.org/react-integration.html
24
25---
26
27## API reference ⚒
28
29### **`observer<P>(baseComponent: FunctionComponent<P>): FunctionComponent<P>`**
30
31The observer converts a component into a reactive component, which tracks which observables are used automatically and re-renders the component when one of these values changes.
32Can only be used for function components. For class component support see the `mobx-react` package.
33
34### **`<Observer>{renderFn}</Observer>`**
35
36Is a React component, which applies observer to an anonymous region in your component. `<Observer>` can be used both inside class and function components.
37
38### **`useLocalObservable<T>(initializer: () => T, annotations?: AnnotationsMap<T>): T`**
39
40Creates an observable object with the given properties, methods and computed values.
41
42Note that computed values cannot directly depend on non-observable values, but only on observable values, so it might be needed to sync properties into the observable using `useEffect` (see the example below at `useAsObservableSource`).
43
44`useLocalObservable` is a short-hand for:
45
46`const [state] = useState(() => observable(initializer(), annotations, { autoBind: true }))`
47
48### **`enableStaticRendering(enable: true)`**
49
50Call `enableStaticRendering(true)` when running in an SSR environment, in which `observer` wrapped components should never re-render, but cleanup after the first rendering automatically. Use `isUsingStaticRendering()` to inspect the current setting.
51
52---
53
54## Deprecated APIs
55
56### **`useObserver<T>(fn: () => T, baseComponentName = "observed", options?: IUseObserverOptions): T`** (deprecated)
57
58_This API is deprecated in 3.\*. It is often used wrong (e.g. to select data rather than for rendering, and `<Observer>` better decouples the rendering from the component updates_
59
60```ts
61interface IUseObserverOptions {
62 // optional custom hook that should make a component re-render (or not) upon changes
63 // Supported in 2.x only
64 useForceUpdate: () => () => void
65}
66```
67
68It 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).
69
70### **`useLocalStore<T, S>(initializer: () => T, source?: S): T`** (deprecated)
71
72_This API is deprecated in 3.\*. Use `useLocalObservable` instead. They do roughly the same, but `useLocalObservable` accepts an set of annotations as second argument, rather than a `source` object. Using `source` is not recommended, see the deprecation message at `useAsObservableSource` for details_
73
74Local observable state can be introduced by using the useLocalStore hook, that runs its initializer function once to create an observable store and keeps it around for a lifetime of a component.
75
76The annotations are similar to the annotations that are passed in to MobX's [`observable`](https://mobx.js.org/observable.html#available-annotations) API, and can be used to override the automatic member inference of specific fields.
77
78### **`useAsObservableSource<T>(source: T): T`** (deprecated)
79
80The 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).
81
82_This API is deprecated in 3.\* as it relies on observables to be updated during rendering which is an anti-pattern. Instead, use `useEffect` to synchronize non-observable values with values. Example:_
83
84```javascript
85// Before:
86function Measurement({ unit }) {
87 const observableProps = useAsObservableSource({ unit })
88 const state = useLocalStore(() => ({
89 length: 0,
90 get lengthWithUnit() {
91 // lengthWithUnit can only depend on observables, hence the above conversion with `useAsObservableSource`
92 return observableProps.unit === "inch"
93 ? `${this.length * 2.54} inch`
94 : `${this.length} cm`
95 }
96 }))
97
98 return <h1>{state.lengthWithUnit}</h1>
99}
100
101// After:
102function Measurement({ unit }) {
103 const state = useLocalObservable(() => ({
104 unit, // the initial unit
105 length: 0,
106 get lengthWithUnit() {
107 // lengthWithUnit can only depend on observables, hence the above conversion with `useAsObservableSource`
108 return this.unit === "inch" ? `${this.length * 2.54} inch` : `${this.length} cm`
109 }
110 }))
111
112 useEffect(() => {
113 // sync the unit from 'props' into the observable 'state'
114 state.unit = unit
115 }, [unit])
116
117 return <h1>{state.lengthWithUnit}</h1>
118}
119```
120
121Note that, at your own risk, it is also possible to not use `useEffect`, but do `state.unit = unit` instead in the rendering.
122This is closer to the old behavior, but React will warn correctly about this if this would affect the rendering of other components.
123
124## Observer batching (deprecated)
125
126_Note: configuring observer batching is only needed when using `mobx-react-lite` 2.0.* or 2.1.*. From 2.2 onward it will be configured automatically based on the availability of react-dom / react-native packages_
127
128[Check out the elaborate explanation](https://github.com/mobxjs/mobx-react/pull/787#issuecomment-573599793).
129
130In short without observer batching the React doesn't guarantee the order component rendering in some cases. We highly recommend that you configure batching to avoid these random surprises.
131
132Import one of these before any React rendering is happening, typically `index.js/ts`. For Jest tests you can utilize [setupFilesAfterEnv](https://jestjs.io/docs/en/configuration#setupfilesafterenv-array).
133
134**React DOM:**
135
136> import 'mobx-react-lite/batchingForReactDom'
137
138**React Native:**
139
140> import 'mobx-react-lite/batchingForReactNative'
141
142### Opt-out
143
144To opt-out from batching in some specific cases, simply import the following to silence the warning.
145
146> import 'mobx-react-lite/batchingOptOut'
147
148### Custom batched updates
149
150Above imports are for a convenience to utilize standard versions of batching. If you for some reason have customized version of batched updates, you can do the following instead.
151
152```js
153import { observerBatching } from "mobx-react-lite"
154observerBatching(customBatchedUpdates)
155```
156
157## Testing
158
159Running the full test suite now requires node 14+
160But the library itself does not have this limitation
161
162In order to avoid memory leaks due to aborted renders from React
163fiber handling or React `StrictMode`, on environments that does not support [FinalizationRegistry](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry), this library needs to
164run timers to tidy up the remains of the aborted renders.
165
166This can cause issues with test frameworks such as Jest
167which require that timers be cleaned up before the tests
168can exit.
169
170### **`clearTimers()`**
171
172Call `clearTimers()` in the `afterEach` of your tests to ensure
173that `mobx-react-lite` cleans up immediately and allows tests
174to exit.