Skip to content

Commit

Permalink
fix(core): fix default is not work when name is length (#2387)
Browse files Browse the repository at this point in the history
* refactor(core): revert field unmount to skip validate

* chore(core): improve code

* fix(core): fix default is not work when name is length
  • Loading branch information
janryWang authored Nov 3, 2021
1 parent 3538b17 commit 0adf07a
Show file tree
Hide file tree
Showing 23 changed files with 137 additions and 72 deletions.
2 changes: 1 addition & 1 deletion packages/core/src/__tests__/effects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import {
onFormValuesChange,
isVoidField,
} from '../'
import { runEffects } from '../shared/effectbox'
import { runEffects } from '../shared/effective'
import { attach, sleep } from './shared'

test('onFormInit/onFormMount/onFormUnmount', () => {
Expand Down
22 changes: 22 additions & 0 deletions packages/core/src/__tests__/field.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1638,3 +1638,25 @@ test('reactions initialValue and value', () => {
)
expect(form.values.aa.input).toEqual('111')
})

test('field name is length in initialize', () => {
const form = attach(createForm())
const field = attach(
form.createField({
name: 'length',
initialValue: 123,
})
)
expect(field.value).toEqual(123)
})

test('field name is length in dynamic assign', () => {
const form = attach(createForm())
const field = attach(
form.createField({
name: 'length',
})
)
field.initialValue = 123
expect(field.value).toEqual(123)
})
8 changes: 4 additions & 4 deletions packages/core/src/__tests__/internals.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {
getValuesFromEvent,
matchFeedback,
patchFieldStates,
setModelState,
serialize,
isHTMLInputEvent,
} from '../shared/internals'

Expand All @@ -28,10 +28,10 @@ test('patchFieldStates', () => {
expect(fields).toEqual({})
})

test('setModelState', () => {
expect(setModelState(null, null)).toBeUndefined()
test('serialize', () => {
expect(serialize(null, null)).toBeUndefined()
expect(
setModelState(
serialize(
{},
{
parent: null,
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/effects/onFieldEffects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
DataField,
IFieldState,
} from '../types'
import { createEffectHook, useEffectForm } from '../shared/effectbox'
import { createEffectHook, useEffectForm } from '../shared/effective'
import { onFormUnmount } from './onFormEffects'

function createFieldEffect<Result extends GeneralField = GeneralField>(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/effects/onFormEffects.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { autorun, batch } from '@formily/reactive'
import { Form } from '../models'
import { LifeCycleTypes } from '../types'
import { createEffectHook } from '../shared/effectbox'
import { createEffectHook } from '../shared/effective'

function createFormEffect(type: LifeCycleTypes) {
return createEffectHook(
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/models/Form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import {
getValidFormValues,
} from '../shared/internals'
import { isVoidField } from '../shared/checkers'
import { runEffects } from '../shared/effectbox'
import { runEffects } from '../shared/effective'
import { ArrayField } from './ArrayField'
import { ObjectField } from './ObjectField'
import { VoidField } from './VoidField'
Expand Down
28 changes: 27 additions & 1 deletion packages/core/src/shared/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,39 @@ export const ReservedProperties = {
indexes: true,
fields: true,
lifecycles: true,
originValues: true,
componentType: true,
componentProps: true,
decoratorType: true,
decoratorProps: true,
}

export const ReadOnlyProperties = {
address: true,
path: true,
valid: true,
invalid: true,
selfValid: true,
selfInvalid: true,
errors: true,
successes: true,
warnings: true,
validateStatus: true,
}

const SELF_DISPLAY = 'selfDisplay'
const SELF_PATTERN = 'selfPattern'

export const MutuallyExclusiveProperties = {
pattern: SELF_PATTERN,
editable: SELF_PATTERN,
readOnly: SELF_PATTERN,
readPretty: SELF_PATTERN,
disabled: SELF_PATTERN,
display: SELF_DISPLAY,
hidden: SELF_DISPLAY,
visible: SELF_DISPLAY,
}

export const RESPONSE_REQUEST_DURATION = 100

export const GlobalState = {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion packages/core/src/shared/externals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
createEffectHook,
createEffectContext,
useEffectForm,
} from './effectbox'
} from './effective'
import {
isArrayField,
isArrayFieldState,
Expand Down
95 changes: 41 additions & 54 deletions packages/core/src/shared/internals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
import {
autorun,
batch,
contains,
toJS,
isObservable,
DataChange,
Expand Down Expand Up @@ -48,8 +49,10 @@ import {
import {
RESPONSE_REQUEST_DURATION,
ReservedProperties,
MutuallyExclusiveProperties,
NumberIndexReg,
GlobalState,
ReadOnlyProperties,
} from './constants'

export const isHTMLInputEvent = (event: any, stopPropagation = true) => {
Expand Down Expand Up @@ -274,6 +277,8 @@ export const validateToFeedbacks = async (
return results
}

const hasOwnProperty = Object.prototype.hasOwnProperty

export const setValidatorRule = (field: Field, name: string, value: any) => {
if (!isValid(value)) return
const hasRule = parseValidatorDescriptions(field.validator).some(
Expand All @@ -285,7 +290,7 @@ export const setValidatorRule = (field: Field, name: string, value: any) => {
if (hasRule) {
if (isArr(field.validator)) {
field.validator = field.validator.map((desc: any) => {
if (Object.prototype.hasOwnProperty.call(desc, name)) {
if (hasOwnProperty.call(desc, name)) {
desc[name] = value
return desc
}
Expand Down Expand Up @@ -588,76 +593,52 @@ export const subscribeUpdate = (
}
}

export const setModelState = (model: any, setter: any) => {
export const serialize = (model: any, setter: any) => {
if (!model) return
const isSkipProperty = (key: string) => {
if (key === 'address' || key === 'path') return true
if (key === 'valid' || key === 'invalid') return true
if (key === 'componentType' || key === 'componentProps') return true
if (key === 'decoratorType' || key === 'decoratorProps') return true
if (key === 'validateStatus') return true
if (key === 'errors' || key === 'warnings' || key === 'successes')
return true
if (
(key === 'display' || key === 'visible' || key === 'hidden') &&
'selfDisplay' in setter &&
!isValid(setter.selfDisplay)
) {
return true
}
if (
(key === 'pattern' ||
key === 'editable' ||
key === 'disabled' ||
key === 'readOnly' ||
key === 'readPretty') &&
'selfPattern' in setter &&
!isValid(setter.selfPattern)
) {
return true
}
return false
}
if (isFn(setter)) {
setter(model)
return model
} else {
Object.keys(setter || {}).forEach((key: string) => {
const value = setter[key]
each(setter, (value, key) => {
if (isFn(value)) return
if (ReservedProperties[key]) return
if (isSkipProperty(key)) return
if (ReadOnlyProperties[key] || ReservedProperties[key]) return
const MutuallyExclusiveKey = MutuallyExclusiveProperties[key]
if (
MutuallyExclusiveKey &&
hasOwnProperty.call(setter, MutuallyExclusiveKey) &&
!isValid(setter[MutuallyExclusiveKey])
)
return
model[key] = value
})
}
return model
}

export const getModelState = (model: any, getter?: any) => {
export const deserialize = (model: any, getter?: any) => {
if (isFn(getter)) {
return getter(model)
} else {
return Object.keys(model || {}).reduce((buf, key: string) => {
const value = model[key]
if (isFn(value)) {
return buf
}
if (ReservedProperties[key]) return buf
const results = {}
each(model, (value, key) => {
if (isFn(value)) return
if (ReservedProperties[key]) return
if (key === 'address' || key === 'path') {
buf[key] = value.toString()
return buf
results[key] = value.toString()
return
}
buf[key] = toJS(value)
return buf
}, {})
results[key] = toJS(value)
})
return results
}
}

export const createStateSetter = (model: any) => {
return batch.bound((state?: any) => setModelState(model, state))
return batch.bound((setter?: any) => serialize(model, setter))
}

export const createStateGetter = (model: any) => {
return (getter?: any) => getModelState(model, getter)
return (getter?: any) => deserialize(model, getter)
}

export const createBatchStateSetter = (form: Form) => {
Expand Down Expand Up @@ -701,8 +682,11 @@ export const triggerFormInitialValuesChange = (
change: DataChange
) => {
const path = change.path
if (path[path.length - 1] === 'length') return
if (path[0] === 'initialValues') {
if (Array.isArray(change.object) && change.key === 'length') return
if (
contains(form.initialValues, change.object) ||
contains(form.initialValues, change.value)
) {
if (change.type === 'add' || change.type === 'set') {
patchFormValues(form, path.slice(1), change.value)
}
Expand All @@ -713,9 +697,12 @@ export const triggerFormInitialValuesChange = (
}

export const triggerFormValuesChange = (form: Form, change: DataChange) => {
const path = change.path
if (path[path.length - 1] === 'length') return
if (path[0] === 'values' && form.initialized) {
if (Array.isArray(change.object) && change.key === 'length') return
if (
(contains(form.values, change.object) ||
contains(form.values, change.value)) &&
form.initialized
) {
form.notify(LifeCycleTypes.ON_FORM_VALUES_CHANGE)
}
}
Expand Down Expand Up @@ -997,7 +984,7 @@ export const getValidFormValues = (values: any) => {
}

export const getValidFieldDefaultValue = (value: any, initialValue: any) => {
if (allowAssignDefaultValue(value, initialValue)) return initialValue
if (allowAssignDefaultValue(value, initialValue)) return clone(initialValue)
return value
}

Expand Down
1 change: 1 addition & 0 deletions packages/reactive/docs/api/observe.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type OperationType =
interface IChange {
key?: PropertyKey
path?: ObservablePath
object?: object
value?: any
oldValue?: any
type?: OperationType
Expand Down
1 change: 1 addition & 0 deletions packages/reactive/docs/api/observe.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type OperationType =
interface IChange {
key?: PropertyKey
path?: ObservablePath
object?: object
value?: any
oldValue?: any
type?: OperationType
Expand Down
14 changes: 14 additions & 0 deletions packages/reactive/src/__tests__/observable.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import { observable } from '../'
import { contains } from '../externals'

test('array mutation', () => {
const arr = observable([1, 2, 3, 4])
arr.splice(2, 1)
expect(arr).toEqual([1, 2, 4])
})

test('observable contains', () => {
const element = { aa: 123 }
const other = { bb: 321 }
const arr = observable<any[]>([element, 2, 3, 4])
const obj = observable<any>({})
expect(contains(arr, arr[0])).toBeTruthy()
expect(contains(obj, obj.other)).toBeFalsy()
obj.other = other
obj.arr = arr
expect(contains(obj, obj.other)).toBeTruthy()
expect(contains(obj, obj.arr)).toBeFalsy()
})
2 changes: 1 addition & 1 deletion packages/reactive/src/annotations/box.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ProxyRaw, RawProxy } from '../environment'
import { createAnnotation } from '../internals'
import { buildDataTree } from '../datatree'
import { buildDataTree } from '../tree'
import {
bindTargetKeyWithCurrentReaction,
runReactionsFromTargetKey,
Expand Down
2 changes: 1 addition & 1 deletion packages/reactive/src/annotations/computed.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ProxyRaw, RawProxy, ReactionStack } from '../environment'
import { createAnnotation } from '../internals'
import { buildDataTree } from '../datatree'
import { buildDataTree } from '../tree'
import {
bindTargetKeyWithCurrentReaction,
runReactionsFromTargetKey,
Expand Down
2 changes: 1 addition & 1 deletion packages/reactive/src/annotations/ref.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ProxyRaw, RawProxy } from '../environment'
import { createAnnotation } from '../internals'
import { buildDataTree } from '../datatree'
import { buildDataTree } from '../tree'
import {
bindTargetKeyWithCurrentReaction,
runReactionsFromTargetKey,
Expand Down
2 changes: 1 addition & 1 deletion packages/reactive/src/environment.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ObservableListener, Reaction, ReactionsMap } from './types'
import { ArraySet } from './array'
import { DataNode } from './datatree'
import { DataNode } from './tree'

export const ProxyRaw = new WeakMap()
export const RawProxy = new WeakMap()
Expand Down
Loading

0 comments on commit 0adf07a

Please sign in to comment.