UNPKG

8.69 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)
4[![Coverage Status](https://coveralls.io/repos/github/mobxjs/mobx-react-lite/badge.svg)](https://coveralls.io/github/mobxjs/mobx-react-lite)
5[![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)
6[![Discuss on Github](https://img.shields.io/badge/discuss%20on-GitHub-orange)](https://github.com/mobxjs/mobx/discussions)
7[![View changelog](https://img.shields.io/badge/changelogs.xyz-Explore%20Changelog-brightgreen)](https://changelogs.xyz/mobx-react-lite)
8
9This 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.
10Unlike `mobx-react`, it doesn't `Provider`/`inject`, as `useContext` can be used instead.
11
12## Compatibility table (major versions)
13
14| mobx | mobx-react-lite | Browser |
15| ---- | --------------- | ---------------------------------------------- |
16| 6 | 3 | Modern browsers (IE 11+ in compatibility mode) |
17| 5 | 2 | Modern browsers |
18| 4 | 2 | IE 11+, RN w/o Proxy support |
19
20`mobx-react-lite` requires React 16.8 or higher.
21
22## User Guide 👉 https://mobx.js.org/react-integration.html
23
24---
25
26## API reference âš’
27
28### **`observer<P>(baseComponent: FunctionComponent<P>): FunctionComponent<P>`**
29
30The 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.
31Can only be used for function components. For class component support see the `mobx-react` package.
32
33### **`<Observer>{renderFn}</Observer>`**
34
35Is a React component, which applies observer to an anonymous region in your component. `<Observer>` can be used both inside class and function components.
36
37### **`useLocalObservable<T>(initializer: () => T, annotations?: AnnotationsMap<T>): T`**
38
39Creates an observable object with the given properties, methods and computed values.
40
41Note 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`).
42
43`useLocalObservable` is a short-hand for:
44
45`const [state] = useState(() => observable(initializer(), annotations, { autoBind: true }))`
46
47### **`enableStaticRendering(enable: true)`**
48
49Call `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.
50
51---
52
53## Deprecated APIs
54
55### **`useObserver<T>(fn: () => T, baseComponentName = "observed", options?: IUseObserverOptions): T`** (deprecated)
56
57_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_
58
59```ts
60interface IUseObserverOptions {
61 // optional custom hook that should make a component re-render (or not) upon changes
62 // Supported in 2.x only
63 useForceUpdate: () => () => void
64}
65```
66
67It 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).
68
69### **`useLocalStore<T, S>(initializer: () => T, source?: S): T`** (deprecated)
70
71_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_
72
73Local 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.
74
75The 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.
76
77### **`useAsObservableSource<T>(source: T): T`** (deprecated)
78
79The 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).
80
81_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:_
82
83```javascript
84// Before:
85function Measurement({ unit }) {
86 const observableProps = useAsObservableSource({ unit })
87 const state = useLocalStore(() => ({
88 length: 0,
89 get lengthWithUnit() {
90 // lengthWithUnit can only depend on observables, hence the above conversion with `useAsObservableSource`
91 return observableProps.unit === "inch"
92 ? `${this.length / 2.54} inch`
93 : `${this.length} cm`
94 }
95 }))
96
97 return <h1>{state.lengthWithUnit}</h1>
98}
99
100// After:
101function Measurement({ unit }) {
102 const state = useLocalObservable(() => ({
103 unit, // the initial unit
104 length: 0,
105 get lengthWithUnit() {
106 // lengthWithUnit can only depend on observables, hence the above conversion with `useAsObservableSource`
107 return this.unit === "inch" ? `${this.length / 2.54} inch` : `${this.length} cm`
108 }
109 }))
110
111 useEffect(() => {
112 // sync the unit from 'props' into the observable 'state'
113 state.unit = unit
114 }, [unit])
115
116 return <h1>{state.lengthWithUnit}</h1>
117}
118```
119
120Note that, at your own risk, it is also possible to not use `useEffect`, but do `state.unit = unit` instead in the rendering.
121This is closer to the old behavior, but React will warn correctly about this if this would affect the rendering of other components.
122
123## Observer batching (deprecated)
124
125_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_
126
127[Check out the elaborate explanation](https://github.com/mobxjs/mobx-react/pull/787#issuecomment-573599793).
128
129In 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.
130
131Import 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).
132
133**React DOM:**
134
135> import 'mobx-react-lite/batchingForReactDom'
136
137**React Native:**
138
139> import 'mobx-react-lite/batchingForReactNative'
140
141### Opt-out
142
143To opt-out from batching in some specific cases, simply import the following to silence the warning.
144
145> import 'mobx-react-lite/batchingOptOut'
146
147### Custom batched updates
148
149Above 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.
150
151```js
152import { observerBatching } from "mobx-react-lite"
153observerBatching(customBatchedUpdates)
154```
155
156## Testing
157
158Running the full test suite now requires node 14+
159But the library itself does not have this limitation
160
161In order to avoid memory leaks due to aborted renders from React
162fiber 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
163run timers to tidy up the remains of the aborted renders.
164
165This can cause issues with test frameworks such as Jest
166which require that timers be cleaned up before the tests
167can exit.
168
169### **`clearTimers()`**
170
171Call `clearTimers()` in the `afterEach` of your tests to ensure
172that `mobx-react-lite` cleans up immediately and allows tests
173to exit.