Skip to content
This repository has been archived by the owner on Dec 31, 2020. It is now read-only.

Commit

Permalink
Opt-in variant of batched updates (#214)
Browse files Browse the repository at this point in the history
* Opt-in variant of batched updates

* Copy types instead of importing

* Document optimizeScheduler

* Try to break the parent/child test

* Fix type declaration
  • Loading branch information
FredyC committed Oct 15, 2019
1 parent c8febca commit 4e39769
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 49 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,31 @@ interface IUseObserverOptions {

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.

## Optimize rendering

[Check out the elaborate explanation](https://github.com/mobxjs/mobx-react-lite/issues/153#issuecomment-490511464).

If this is something that concerns you, we have prepared files you can simply import to configure MobX to use React batched updates depending on your platform.

**React DOM:**

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

> import 'mobx-react-lite/optimizeForReactNative'
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).

### Custom batched updates

Above imports are for a convenience. If you for some reason have customized version of batched updates, you can do the following instead.

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

## Deprecation notice ⚠

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.
Expand Down
2 changes: 2 additions & 0 deletions optimizeForReactDom.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const { unstable_batchedUpdates } = require("react-dom")
require("./dist").optimizeScheduler(unstable_batchedUpdates)
2 changes: 2 additions & 0 deletions optimizeForReactNative.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
const { unstable_batchedUpdates } = require("react-native")
require("./dist").optimizeScheduler(unstable_batchedUpdates)
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ export { Observer } from "./ObserverComponent"
export { useForceUpdate } from "./utils"
export { useAsObservableSource } from "./useAsObservableSource"
export { useLocalStore } from "./useLocalStore"
export { optimizeScheduler } from "./optimizeScheduler"
17 changes: 17 additions & 0 deletions src/optimizeScheduler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { configure } from "mobx"

export interface IBatchedUpdates {
batchedUpdates<A, B>(callback: (a: A, b: B) => any, a: A, b: B): void
batchedUpdates<A>(callback: (a: A) => any, a: A): void
batchedUpdates(callback: () => any): void
}

export const optimizeScheduler = (reactionScheduler: IBatchedUpdates) => {
if (typeof reactionScheduler === "function") {
configure({ reactionScheduler })
}
}

export const deoptimizeScheduler = () => {
configure({ reactionScheduler: undefined })
}
102 changes: 54 additions & 48 deletions test/observer.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { act, cleanup, fireEvent, render } from "@testing-library/react"
import mockConsole from "jest-mock-console"
import * as mobx from "mobx"
import * as React from "react"
import { act, cleanup, fireEvent, render } from "@testing-library/react"

import { observer, useObserver, useStaticRendering } from "../src"

Expand Down Expand Up @@ -597,60 +597,66 @@ it("should have the correct displayName", () => {
expect((TestComponent as any).type.displayName).toBe("MyComponent")
})

// test("parent / childs render in the right order", done => {
// // See: https://jsfiddle.net/gkaemmer/q1kv7hbL/13/
// let events = []
test("parent / childs render in the right order", done => {
// See: https://jsfiddle.net/gkaemmer/q1kv7hbL/13/
const events: string[] = []

// class User {
// @mobx.observable
// name = "User's name"
// }
class User {
public name = "User's name"
}

// class Store {
// @mobx.observable
// user = new User()
// @mobx.action
// logout() {
// this.user = null
// }
// }
mobx.decorate(User, { name: mobx.observable })

// function tryLogout() {
// try {
// // ReactDOM.unstable_batchedUpdates(() => {
// store.logout()
// expect(true).toBeTruthy(true)
// // });
// } catch (e) {
// // t.fail(e)
// }
// }
class Store {
public user: User | null = new User()
public logout() {
this.user = null
}
}

// const store = new Store()

// const Parent = observer(() => {
// events.push("parent")
// if (!store.user) return <span>Not logged in.</span>
// return (
// <div>
// <Child />
// <button onClick={tryLogout}>Logout</button>
// </div>
// )
// })
mobx.decorate(Store, {
user: mobx.observable,
logout: mobx.action
})

// const Child = observer(() => {
// events.push("child")
// return <span>Logged in as: {store.user.name}</span>
// })
const store = new Store()

// const container = TestUtils.renderIntoDocument(<Parent />)
function tryLogout() {
try {
store.logout()
expect(true).toBeTruthy()
} catch (e) {
// t.fail(e)
}
}

// debugger
// tryLogout()
// expect(events).toEqual(["parent", "child", "parent"])
// done()
// })
const Parent = observer(() => {
events.push("parent")
if (!store.user) {
return <span>Not logged in.</span>
}
return (
<div>
<Child />
<button onClick={tryLogout}>Logout</button>
</div>
)
})

const Child = observer(() => {
events.push("child")
if (!store.user) {
return null
}
return <span>Logged in as: {store.user.name}</span>
})

render(<Parent />)

tryLogout()
expect(events).toEqual(["parent", "child", "parent"])
done()
})

// describe("206 - @observer should produce usefull errors if it throws", () => {
// const data = mobx.observable({ x: 1 })
Expand Down
3 changes: 2 additions & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"jsRules": {},
"rules": {
"object-literal-sort-keys": false,
"ordered-imports": false
"ordered-imports": false,
"max-classes-per-file": false
},
"rulesDirectory": []
}

0 comments on commit 4e39769

Please sign in to comment.