Skip to content

Commit

Permalink
MobX 6 support (#34)
Browse files Browse the repository at this point in the history
* MobX 6 support

* v2.0.0-beta.1

* update node version for ci
  • Loading branch information
nighca authored Dec 7, 2020
1 parent 0e82a2f commit c746613
Show file tree
Hide file tree
Showing 8 changed files with 2,572 additions and 903 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:

strategy:
matrix:
node-version: [8.x, 10.x, 12.x]
node-version: [10.x, 12.x, 14.x]

steps:
- uses: actions/checkout@v1
Expand Down
3,374 changes: 2,502 additions & 872 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "formstate-x",
"version": "1.2.0",
"version": "2.0.0-beta.1",
"description": "Extended alternative for formstate",
"repository": {
"type": "git",
Expand All @@ -26,20 +26,20 @@
"formstate"
],
"peerDependencies": {
"mobx": ">=4.0.0"
"mobx": ">=6.0.0"
},
"author": "[email protected]",
"license": "Apache-2.0",
"devDependencies": {
"@types/jest": "^25.2.1",
"@types/node": "^12.7.12",
"formstate": "^1.0.0",
"jest": "^25.2.7",
"mobx": "^5.15.4",
"ts-jest": "^25.3.1",
"formstate": "^2.0.0",
"jest": "~26.6.1",
"mobx": "^6.0.4",
"ts-jest": "~26.4.2",
"typedoc": "~0.16.11",
"typedoc-twilio-theme": "^1.0.0",
"typescript": "^3.6.3"
"typescript": "~4.0.3"
},
"dependencies": {}
}
24 changes: 13 additions & 11 deletions src/fieldState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { observable, computed, action, reaction, autorun, runInAction, when } from 'mobx'
import { observable, computed, action, reaction, autorun, when, makeObservable } from 'mobx'
import { ComposibleValidatable, Validator, Validated, ValidationResponse, ValidateStatus, Error, ValidateResult } from './types'
import { applyValidators, debounce, isPromiseLike } from './utils'
import Disposable from './disposable'
Expand Down Expand Up @@ -137,15 +137,15 @@ export default class FieldState<TValue> extends Disposable implements Composible
return
}

runInAction('set-validateStatus-when-_validate', () => {
action('set-validateStatus-when-_validate', () => {
this._validateStatus = ValidateStatus.Validating
})
})()

const response = applyValidators(value, this._validators)

runInAction('set-validation-when-_validate', () => {
action('set-validation-when-_validate', () => {
this.validation = { value, response }
})
})()
}

/**
Expand All @@ -154,11 +154,11 @@ export default class FieldState<TValue> extends Disposable implements Composible
async validate(): Promise<ValidateResult<TValue>> {
const validation = this.validation

runInAction('activate-and-sync-_value-when-validate', () => {
action('activate-and-sync-_value-when-validate', () => {
this._activated = true
// 若有用户交互产生的变更(因 debounce)尚未同步,同步之,确保本次 validate 结果是相对稳定的
this.value = this._value
})
})()

// 若 `validation` 未发生变更,意味着未发生新的校验行为
// 若上边操作未触发自动的校验行为,强制调用之
Expand Down Expand Up @@ -219,19 +219,21 @@ export default class FieldState<TValue> extends Disposable implements Composible
return
}

runInAction('endValidation', () => {
action('endValidation', () => {
this.validation = undefined
this._validateStatus = ValidateStatus.Validated

if (error !== this.error) {
this.setError(error)
}
})
})()
}

constructor(private initialValue: TValue, delay = 200) {
super()

makeObservable(this)

this.reset()

// debounced reaction to `_value` change
Expand All @@ -242,11 +244,11 @@ export default class FieldState<TValue> extends Disposable implements Composible
// see https://github.com/mobxjs/mobx/issues/1956
debounce(() => {
if (this.value !== this._value) {
runInAction('sync-value-when-_value-changed', () => {
action('sync-value-when-_value-changed', () => {
this.value = this._value
this._validateStatus = ValidateStatus.NotValidated
this._activated = true
})
})()
}
}, delay),
{ name: 'reaction-when-_value-change' }
Expand Down
22 changes: 12 additions & 10 deletions src/formState.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { observable, computed, isArrayLike, isObservable, action, autorun, runInAction, when, reaction } from 'mobx'
import { observable, computed, isObservable, action, autorun, when, reaction, makeObservable } from 'mobx'
import { ComposibleValidatable, ValueOfFields, ValidationResponse, Validator, Validated, ValidateStatus, Error, ValidateResult } from './types'
import { applyValidators, isPromiseLike } from './utils'
import { applyValidators, isPromiseLike, isArrayLike } from './utils'
import Disposable from './disposable'

/** Mode: object */
Expand Down Expand Up @@ -187,24 +187,24 @@ export default class FormState<TFields extends ValidatableFields, TValue = Value
private _validate() {
const value = this.value

runInAction('set-validateStatus-when-_validate', () => {
action('set-validateStatus-when-_validate', () => {
this._validateStatus = ValidateStatus.Validating
})
})()

const response = applyValidators(value, this._validators)

runInAction('set-validation-when-_validate', () => {
action('set-validation-when-_validate', () => {
this.validation = { value, response }
})
})()
}

/**
* Fire a validation behavior.
*/
async validate(): Promise<ValidateResult<TValue>> {
runInAction('activate-when-validate', () => {
action('activate-when-validate', () => {
this._activated = true
})
})()

this._validate()
this.fields.forEach(
Expand Down Expand Up @@ -262,19 +262,21 @@ export default class FormState<TFields extends ValidatableFields, TValue = Value
return
}

runInAction('endValidation', () => {
action('endValidation', () => {
this.validation = undefined
this._validateStatus = ValidateStatus.Validated

if (error !== this.error) {
this.setError(error)
}
})
})()
}

constructor(initialFields: TFields) {
super()

makeObservable(this)

this.mode = isArrayLike(initialFields) ? 'array' : 'object'
this.$ = initialFields

Expand Down
31 changes: 30 additions & 1 deletion src/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { asyncResponsesAnd, isEmpty } from './utils'
import { observable } from 'mobx'
import { asyncResponsesAnd, isEmpty, isArrayLike } from './utils'

const defaultDelay = 10

Expand Down Expand Up @@ -61,3 +62,31 @@ describe('asyncResponsesAnd', () => {
expect(result3).toBe('too long')
})
})

describe('isArrayLike', () => {
it('should work well with array', () => {
expect(isArrayLike([])).toBe(true)
expect(isArrayLike([1, 2, 3])).toBe(true)
})
it('should work well with observable array', () => {
expect(isArrayLike(observable([]))).toBe(true)
expect(isArrayLike(observable([1, 2, 3]))).toBe(true)
})
it('should recognize non-object values', () => {
expect(isArrayLike(null)).toBe(false)
expect(isArrayLike(undefined)).toBe(false)
expect(isArrayLike(0)).toBe(false)
expect(isArrayLike('123')).toBe(false)
expect(isArrayLike(/abc/)).toBe(false)
})
it('should recognize normal objects', () => {
expect(isArrayLike({})).toBe(false)
expect(isArrayLike({ 0: 'a' })).toBe(false)
expect(isArrayLike({ a: 1, b: 2 })).toBe(false)
expect(isArrayLike(observable({ a: 1, b: 2 }))).toBe(false)
})
it('should recognize object with invalid length', () => {
expect(isArrayLike({ length: -1 })).toBe(false)
expect(isArrayLike({ length: 2.3 })).toBe(false)
})
})
7 changes: 6 additions & 1 deletion src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Validator, ValidationResponse, ValidatorResponse } from "./types"
import { isObservableArray, IObservableArray } from 'mobx'
import { Validator, ValidationResponse, ValidatorResponse } from './types'

export function isPromiseLike(arg: any): arg is Promise<any> {
return arg != null && typeof arg === 'object' && typeof arg.then === 'function'
Expand Down Expand Up @@ -65,3 +66,7 @@ export function debounce(fn: () => void, delay: number) {
timeout = setTimeout(fn, delay)
}
}

export function isArrayLike(value: unknown): value is unknown[] | IObservableArray {
return Array.isArray(value) || isObservableArray(value)
}
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"moduleResolution": "node",
"strict": true,
"experimentalDecorators": true,
"useDefineForClassFields": true,
"outDir": "./lib",
"lib": ["es2015"]
},
Expand Down

0 comments on commit c746613

Please sign in to comment.