Skip to content

Commit

Permalink
Migrate mobx-react-lite as package
Browse files Browse the repository at this point in the history
  • Loading branch information
danielkcz committed Nov 6, 2020
1 parent 81a2f86 commit 5d5eb89
Show file tree
Hide file tree
Showing 66 changed files with 4,569 additions and 200 deletions.
42 changes: 22 additions & 20 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,27 @@ version: 2.1
executors:
node-executor:
docker:
- image: circleci/node:12
- image: circleci/node:14
environment:
CI: true

orbs:
node: circleci/[email protected]

jobs:
install:
build:
executor: node-executor
steps:
- checkout
- node/install-packages:
pkg-manager: yarn

- run: yarn lint

- run: yarn mobx build --target test
- run: yarn mobx-react build --target test
- run: yarn mobx-react-lite build --target test

- persist_to_workspace:
root: .
paths: [./*]
Expand All @@ -26,41 +33,36 @@ jobs:
steps:
- attach_workspace:
at: .
- run: yarn mobx build test
- run: yarn lint

- run: yarn test -i

mobx:
- run: yarn mobx test:size
- run: yarn mobx-react test:size
- run: yarn mobx-react-lite test:size

mobx-test:
executor: node-executor
steps:
- attach_workspace:
at: .
- run: yarn mobx build

- run: yarn mobx test:flow
- run: yarn mobx test:size
- run:
command: yarn mobx test:performance
environment:
PERSIST: true
- store_artifacts:
path: packages/mobx/perf_report
destination: mobx-perf
mobx-react:
executor: node-executor
steps:
- attach_workspace:
at: .
- run: yarn mobx build test
- run: yarn mobx test:size

workflows:
version: 2
main:
jobs:
- install
- build
- test:
requires: [install]
- mobx:
requires: [install]
- mobx-react:
requires: [install]
requires:
- "build"
- mobx-test:
requires:
- "build"
3 changes: 2 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
website/**/*
dist/
docs/assets/
*.yml
*.yml
coverage
16 changes: 14 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@
"scripts": {
"test": "jest",
"coverage": "jest --coverage",
"lint": "eslint packages/*/src/**/*",
"lint": "eslint packages/*/src/**/* --ext .js,.ts,.tsx",
"prettier": "prettier --write **/*.{js,ts,md}",
"release": "yarn changeset publish",
"mobx": "yarn workspace mobx",
"mobx-react": "yarn workspace mobx-react",
"mobx-react-lite": "yarn workspace mobx-react-lite",
"mobx-undecorate": "yarn workspace mobx-undecorate",
"docs:build": "yarn --cwd website build",
"docs:start": "yarn --cwd website start",
Expand All @@ -23,8 +24,14 @@
"devDependencies": {
"@changesets/changelog-github": "^0.2.7",
"@changesets/cli": "^2.11.0",
"@testing-library/jest-dom": "^5.1.1",
"@testing-library/react": "^11.1.1",
"@testing-library/react-hooks": "3.4.2",
"@types/jest": "^26.0.15",
"@types/node": "12",
"@types/node": "14",
"@types/prop-types": "^15.5.2",
"@types/react": "^16.8.24",
"@types/react-dom": "^16.0.5",
"@typescript-eslint/eslint-plugin": "^4.6.1",
"@typescript-eslint/parser": "^4.1.1",
"coveralls": "^3.1.0",
Expand All @@ -37,10 +44,15 @@
"jest": "^26.6.2",
"jest-mock-console": "^1.0.1",
"lint-staged": "^10.1.7",
"lodash": "^4.17.4",
"minimist": "^1.2.5",
"mkdirp": "1.0.4",
"prettier": "^2.0.5",
"pretty-quick": "3.1.0",
"prop-types": "15.6.2",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-test-renderer": "^17.0.0",
"serializr": "^2.0.3",
"tape": "^5.0.1",
"ts-jest": "26.4.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/mobx-react-lite/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
dist/
lib/
es/
10 changes: 10 additions & 0 deletions packages/mobx-react-lite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/node_modules/

dist/
coverage/

.DS_Store

npm-debug.log*
yarn-debug.log*
yarn-error.log*
22 changes: 22 additions & 0 deletions packages/mobx-react-lite/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# mobx-react-lite

## 3.1.0

### Minor Changes

- [`a0e5fea`](https://github.com/mobxjs/mobx-react-lite/commit/a0e5feaeede68b0bac035f60bf2a7edff3fa1269) [#329](https://github.com/mobxjs/mobx-react-lite/pull/329) Thanks [@RoystonS](https://github.com/RoystonS)! - expose `clearTimers` function to tidy up background timers, allowing test frameworks such as Jest to exit immediately

### Patch Changes

- [`fafb136`](https://github.com/mobxjs/mobx-react-lite/commit/fafb136cce2847b83174cbd15af803442a9a0023) [#332](https://github.com/mobxjs/mobx-react-lite/pull/332) Thanks [@Bnaya](https://github.com/Bnaya)! - Introduce alternative way for managing cleanup of reactions.
This is internal change and shouldn't affect functionality of the library.

## 3.0.1

### Patch Changes

- [`570e8d5`](https://github.com/mobxjs/mobx-react-lite/commit/570e8d594bac415cf9a6c6771080fec043161d0b) [#328](https://github.com/mobxjs/mobx-react-lite/pull/328) Thanks [@mweststrate](https://github.com/mweststrate)! - If observable data changed between mount and useEffect, the render reaction would incorrectly be disposed causing incorrect suspension of upstream computed values

* [`1d6f0a8`](https://github.com/mobxjs/mobx-react-lite/commit/1d6f0a8dd0ff34d7e7cc71946ed670c31193572d) [#326](https://github.com/mobxjs/mobx-react-lite/pull/326) Thanks [@FredyC](https://github.com/FredyC)! - No important changes, just checking new setup for releases.

> Prior 3.0.0 see GitHub releases for changelog
21 changes: 21 additions & 0 deletions packages/mobx-react-lite/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2015 Michel Weststrate

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
174 changes: 174 additions & 0 deletions packages/mobx-react-lite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# mobx-react-lite

[![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)

[![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)

[![Discuss on Github](https://img.shields.io/badge/discuss%20on-GitHub-orange)](https://github.com/mobxjs/mobx/discussions)
[![View changelog](https://img.shields.io/badge/changelogs.xyz-Explore%20Changelog-brightgreen)](https://changelogs.xyz/mobx-react-lite)

This 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.
Unlike `mobx-react`, it doesn't `Provider`/`inject`, as `useContext` can be used instead.

## Compatibility table (major versions)

| mobx | mobx-react-lite | Browser |
| ---- | --------------- | ---------------------------------------------- |
| 6 | 3 | Modern browsers (IE 11+ in compatibility mode) |
| 5 | 2 | Modern browsers |
| 4 | 2 | IE 11+, RN w/o Proxy support |

`mobx-react-lite` requires React 16.8 or higher.

## User Guide 👉 https://mobx.js.org/react-integration.html

---

## API reference ⚒

### **`observer<P>(baseComponent: FunctionComponent<P>): FunctionComponent<P>`**

The 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.
Can only be used for function components. For class component support see the `mobx-react` package.

### **`<Observer>{renderFn}</Observer>`**

Is a React component, which applies observer to an anonymous region in your component. `<Observer>` can be used both inside class and function components.

### **`useLocalObservable<T>(initializer: () => T, annotations?: AnnotationsMap<T>): T`**

Creates an observable object with the given properties, methods and computed values.

Note 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`).

`useLocalObservable` is a short-hand for:

`const [state] = useState(() => observable(initializer(), annotations, { autoBind: true }))`

### **`enableStaticRendering(enable: true)`**

Call `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.

---

## Deprecated APIs

### **`useObserver<T>(fn: () => T, baseComponentName = "observed", options?: IUseObserverOptions): T`** (deprecated)

_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_

```ts
interface IUseObserverOptions {
// optional custom hook that should make a component re-render (or not) upon changes
// Supported in 2.x only
useForceUpdate: () => () => void
}
```

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).

### **`useLocalStore<T, S>(initializer: () => T, source?: S): T`** (deprecated)

_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_

Local 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.

The 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.

### **`useAsObservableSource<T>(source: T): T`** (deprecated)

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).

_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:_

```javascript
// Before:
function Measurement({ unit }) {
const observableProps = useAsObservableSource({ unit })
const state = useLocalStore(() => ({
length: 0,
get lengthWithUnit() {
// lengthWithUnit can only depend on observables, hence the above conversion with `useAsObservableSource`
return observableProps.unit === "inch"
? `${this.length * 2.54} inch`
: `${this.length} cm`
}
}))

return <h1>{state.lengthWithUnit}</h1>
}

// After:
function Measurement({ unit }) {
const state = useLocalObservable(() => ({
unit, // the initial unit
length: 0,
get lengthWithUnit() {
// lengthWithUnit can only depend on observables, hence the above conversion with `useAsObservableSource`
return this.unit === "inch" ? `${this.length * 2.54} inch` : `${this.length} cm`
}
}))

useEffect(() => {
// sync the unit from 'props' into the observable 'state'
state.unit = unit
}, [unit])

return <h1>{state.lengthWithUnit}</h1>
}
```

Note that, at your own risk, it is also possible to not use `useEffect`, but do `state.unit = unit` instead in the rendering.
This is closer to the old behavior, but React will warn correctly about this if this would affect the rendering of other components.

## Observer batching (deprecated)

_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_

[Check out the elaborate explanation](https://github.com/mobxjs/mobx-react/pull/787#issuecomment-573599793).

In 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.

Import 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).

**React DOM:**

> import 'mobx-react-lite/batchingForReactDom'
**React Native:**

> import 'mobx-react-lite/batchingForReactNative'
### Opt-out

To opt-out from batching in some specific cases, simply import the following to silence the warning.

> import 'mobx-react-lite/batchingOptOut'
### Custom batched updates

Above 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.

```js
import { observerBatching } from "mobx-react-lite"
observerBatching(customBatchedUpdates)
```

## Testing

Running the full test suite now requires node 14+
But the library itself does not have this limitation

In order to avoid memory leaks due to aborted renders from React
fiber 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
run timers to tidy up the remains of the aborted renders.

This can cause issues with test frameworks such as Jest
which require that timers be cleaned up before the tests
can exit.

### **`clearTimers()`**

Call `clearTimers()` in the `afterEach` of your tests to ensure
that `mobx-react-lite` cleans up immediately and allows tests
to exit.
5 changes: 5 additions & 0 deletions packages/mobx-react-lite/__tests__/.eslintrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
env:
jest: true
rules:
"react/display-name": "off"
"react/prop-types": "off"
Loading

0 comments on commit 5d5eb89

Please sign in to comment.