Gathering detailed insights and metrics for @ifcloud-formily/react
Gathering detailed insights and metrics for @ifcloud-formily/react
Gathering detailed insights and metrics for @ifcloud-formily/react
Gathering detailed insights and metrics for @ifcloud-formily/react
📱🚀 🧩 Cross Device & High Performance Normal Form/Dynamic(JSON Schema) Form/Form Builder -- Support React/React Native/Vue 2/Vue 3
npm install @ifcloud-formily/react
Typescript
Module System
Node Version
NPM Version
TypeScript (78.44%)
Vue (13.05%)
JavaScript (3.87%)
SCSS (2.75%)
Less (1.62%)
Stylus (0.18%)
EJS (0.09%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
12,072 Stars
3,164 Commits
1,550 Forks
165 Watchers
10 Branches
208 Contributors
Updated on Jul 14, 2025
Latest Version
1.5.6
Package Id
@ifcloud-formily/react@1.5.6
Unpacked Size
332.14 kB
Size
54.86 kB
File Count
74
NPM Version
lerna/3.22.1/node@v12.19.0+x64 (linux)
Node Version
12.19.0
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
2
5
1
English | 简体中文
@ifcloud-formily/react is based on
react
and @ifcloud-formily/core is already built in. It provide API to manuplate form state and components for rendering support. it mainly includes:
- Form
- Field
- VirtualField
- FormaSpy
- FormProvider
- FormConsumer(deprecated,pls using FormSpy)
- createFormActions (create sync API to manuplate form state)
- createAsyncFormActions (create async API to manuplate form state)
- FormEffectHooks (LifeCycles Hook)
1npm install --save @ifcloud-formily/react
Usage
IForm
Imutators
IFormActions
IFormAsyncActions
IFieldState
IVirtualFieldState
IFormSpyProps
IFieldHook
IVirtualFieldHook
ISpyHook
SyncValidateResponse
AsyncValidateResponse
ValidateResponse
InternalFormats
CustomValidator
ValidateDescription
ValidateArrayRules
ValidatePatternRules
IFieldAPI
IVirtualFieldAPI
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 FormPath, 7 createFormActions, 8 FormSpy, 9 FormProvider, 10 FormConsumer, 11 FormEffectHooks 12} from '@ifcloud-formily/react' 13 14const { onFormInit$, onFormInputChange$, onFieldInputChange$ } = FormEffectHooks 15const actions = createFormActions() 16const App = () => { 17 return ( 18 <Form 19 actions={actions} 20 effects={() => { 21 onFormInit$().subscribe(() => { 22 console.log('initialized') 23 }) 24 onFieldInputChange$().subscribe(state => { 25 console.log('field change', state) 26 }) 27 }} 28 onChange={() => {}} 29 > 30 <React.Fragment> 31 <label>username: </label> 32 <Field name="username"> 33 {({ state, mutators }) => ( 34 <React.Fragment> 35 <input 36 disabled={!state.editable} 37 value={state.value || ''} 38 onChange={mutators.change} 39 onBlur={mutators.blur} 40 onFocus={mutators.focus} 41 /> 42 {state.errors} 43 {state.warnings} 44 </React.Fragment> 45 )} 46 </Field> 47 </React.Fragment> 48 </Form> 49 ) 50} 51ReactDOM.render(<App />, document.getElementById('root'))
Example:Show you how to bind the <input>
field and subsequent examples are based on this field
1const InputField = props => ( 2 <Field {...props}> 3 {({ state, mutators }) => ( 4 <div> 5 <input 6 disabled={!state.editable} 7 value={state.value || ''} 8 onChange={mutators.change} 9 onBlur={mutators.blur} 10 onFocus={mutators.focus} 11 /> 12 {state.errors} 13 {state.warnings} 14 </div> 15 )} 16 </Field> 17)
Example:required validation + error type validation + warning type validation + custom validation The type of rules is ValidatePatternRules which is InternalFormats | CustomValidator | ValidateDescription | ValidateArrayRules
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const App = () => { 25 return ( 26 <Form actions={actions}> 27 <h5>required validation</h5> 28 <span>username</span> 29 <InputField name="username" required /> 30 31 <h5>error type validation</h5> 32 <span>age</span> 33 <InputField 34 name="age" 35 rules={[ 36 val => 37 !val ? { type: 'error', message: 'age is required' } : undefined 38 ]} 39 /> 40 41 <h5>warning type validation</h5> 42 <span>gender</span> 43 <InputField 44 name="gender" 45 rules={[ 46 val => 47 !val 48 ? { type: 'warning', message: 'gender is required' } 49 : undefined 50 ]} 51 /> 52 53 <h5>built-in validation default to error type validation</h5> 54 <span>id</span> 55 <InputField 56 name="id" 57 rules={[ 58 { 59 format: 'number', 60 message: 'id is not a number.' 61 } 62 ]} 63 /> 64 65 <h5>custom validation</h5> 66 <span>verifyCode</span> 67 <InputField 68 name="verifyCode" 69 rules={[ 70 { 71 validator(value) { 72 return !value 73 ? 'This field can not be empty, please enter {{scope.outerVariable}}' 74 : undefined 75 }, 76 scope: { 77 outerVariable: '456' 78 } 79 }, 80 81 { 82 validator(value) { 83 return value === '456' 84 ? { type: 'error', message: 'This field can not be 456' } 85 : undefined 86 } 87 } 88 ]} 89 /> 90 91 <div> 92 <button 93 onClick={() => { 94 const result = actions.validate() 95 console.log(actions.getFormState(state => state.values)) 96 result.then(validateResp => { 97 console.log(validateResp) 98 }) 99 }} 100 > 101 validate 102 </button> 103 </div> 104 </Form> 105 ) 106} 107 108ReactDOM.render(<App />, document.getElementById('root'))
Example:User info user(username, age)
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const App = () => { 25 return ( 26 <Form actions={actions}> 27 <span>user</span> 28 <Field 29 name="user" 30 initialValue={{ 31 username: undefined, 32 age: undefined 33 }} 34 > 35 {({ state, mutators }) => { 36 return ( 37 <React.Fragment> 38 {Object.keys(state.value).map(key => { 39 if (!mutators.exist(key)) return 40 41 return ( 42 <div key={key}> 43 <span>{key}</span> 44 <InputField name={`user.${key}`} /> 45 <button 46 onClick={() => { 47 mutators.remove(key) 48 }} 49 > 50 x 51 </button> 52 </div> 53 ) 54 })} 55 <button 56 onClick={() => { 57 mutators.change({ 58 ...state.value, 59 [new Date().getTime()]: new Date().getTime() 60 }) 61 }} 62 > 63 + 64 </button> 65 <button 66 onClick={() => { 67 console.log( 68 'values', 69 actions.getFormState(state => state.values) 70 ) 71 }} 72 > 73 print 74 </button> 75 </React.Fragment> 76 ) 77 }} 78 </Field> 79 </Form> 80 ) 81} 82 83ReactDOM.render(<App />, document.getElementById('root'))
Example:Id list
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const App = () => { 25 return ( 26 <Form actions={actions}> 27 <Field name="idList" initialValue={['1', '2', '3']}> 28 {({ state, mutators }) => { 29 return ( 30 <React.Fragment> 31 {state.value.map((item, index) => { 32 return ( 33 <div key={index}> 34 <InputField name={`idList[${index}]`} /> 35 <button onClick={() => mutators.remove(index)}> 36 Remove 37 </button> 38 </div> 39 ) 40 })} 41 <button onClick={() => mutators.push()}>Add Item</button> 42 </React.Fragment> 43 ) 44 }} 45 </Field> 46 </Form> 47 ) 48} 49 50ReactDOM.render(<App />, document.getElementById('root'))
Example:User list
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const App = () => { 25 return ( 26 <Form actions={actions}> 27 <Field 28 name="userList" 29 initialValue={[ 30 { username: 'bobby', age: 21 }, 31 { username: 'lily', age: 20 } 32 ]} 33 > 34 {({ state, mutators }) => { 35 return ( 36 <React.Fragment> 37 {state.value.map((item, index) => { 38 return ( 39 <div key={index}> 40 <Field name={`userList[${index}]`} initialValue={{}}> 41 {({ state: innerState, mutators: innerMutator }) => { 42 return ( 43 <React.Fragment> 44 {Object.keys(innerState.value).map(key => { 45 if (!innerMutator.exist(key)) return 46 return ( 47 <React.Fragment key={key}> 48 <InputField 49 name={`userList[${index}].${key}`} 50 /> 51 <button 52 onClick={() => { 53 innerMutator.remove(key) 54 }} 55 > 56 x 57 </button> 58 </React.Fragment> 59 ) 60 })} 61 <button 62 onClick={() => { 63 innerMutator.change({ 64 ...innerState.value, 65 [new Date().getTime()]: new Date().getTime() 66 }) 67 }} 68 > 69 + 70 </button> 71 </React.Fragment> 72 ) 73 }} 74 </Field> 75 76 <button onClick={() => mutators.remove(index)}> 77 Remove 78 </button> 79 </div> 80 ) 81 })} 82 <button 83 onClick={() => 84 mutators.push({ 85 username: undefined, 86 age: undefined 87 }) 88 } 89 > 90 Add Item 91 </button> 92 <button 93 onClick={() => 94 console.log(actions.getFormState(state => state.values)) 95 } 96 > 97 print 98 </button> 99 </React.Fragment> 100 ) 101 }} 102 </Field> 103 </Form> 104 ) 105} 106 107ReactDOM.render(<App />, document.getElementById('root'))
Example: see how display
与 visible
affect values
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 createFormActions, 7 LifeCycleTypes, 8 FormSpy 9} from '@ifcloud-formily/react' 10 11const InputField = props => ( 12 <Field {...props}> 13 {({ state, mutators }) => { 14 const loading = state.props.loading 15 return ( 16 <React.Fragment> 17 {props.label && <label>{props.label}</label>} 18 {loading ? ( 19 ' loading... ' 20 ) : ( 21 <input 22 disabled={!state.editable} 23 value={state.value || ''} 24 onChange={mutators.change} 25 onBlur={mutators.blur} 26 onFocus={mutators.focus} 27 /> 28 )} 29 <span style={{ color: 'red' }}>{state.errors}</span> 30 <span style={{ color: 'orange' }}>{state.warnings}</span> 31 </React.Fragment> 32 ) 33 }} 34 </Field> 35) 36 37const CheckedField = props => ( 38 <Field {...props}> 39 {({ state, mutators }) => { 40 const loading = state.props.loading 41 return ( 42 <React.Fragment> 43 {props.label && <label>{props.label}</label>} 44 {loading ? ( 45 ' loading... ' 46 ) : ( 47 <input 48 type="checkbox" 49 onChange={() => { 50 mutators.change(!state.value) 51 }} 52 checked={!!state.value} 53 /> 54 )} 55 <span style={{ color: 'red' }}>{state.errors}</span> 56 <span style={{ color: 'orange' }}>{state.warnings}</span> 57 </React.Fragment> 58 ) 59 }} 60 </Field> 61) 62 63const actions = createFormActions() 64const App = () => { 65 return ( 66 <Form 67 actions={actions} 68 effects={($, { validate, setFieldState }) => { 69 $(LifeCycleTypes.ON_FORM_INIT).subscribe(() => { 70 setFieldState('displayTrigger', state => (state.value = true)) 71 setFieldState('visibleTrigger', state => (state.value = true)) 72 setFieldState('a', state => (state.value = 1)) 73 setFieldState('b', state => (state.value = 2)) 74 }) 75 76 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'visibleTrigger').subscribe( 77 fieldState => { 78 setFieldState('a', state => { 79 state.visible = fieldState.value 80 }) 81 } 82 ) 83 84 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'displayTrigger').subscribe( 85 fieldState => { 86 setFieldState('b', state => { 87 state.display = fieldState.value 88 }) 89 } 90 ) 91 }} 92 > 93 <div> 94 <CheckedField label="visible" name="visibleTrigger" /> 95 96 <InputField name="a" label="a" /> 97 </div> 98 <div> 99 <CheckedField label="display" name="displayTrigger" /> 100 <InputField name="b" label="b" /> 101 </div> 102 103 <FormSpy> 104 {({ state, form }) => { 105 return ( 106 <div> 107 {JSON.stringify(form.getFormState(state => state.values))} 108 </div> 109 ) 110 }} 111 </FormSpy> 112 113 <button 114 onClick={() => console.log(actions.getFormState(state => state.values))} 115 > 116 print 117 </button> 118 </Form> 119 ) 120} 121 122ReactDOM.render(<App />, document.getElementById('root'))
Example:Show/hide field and modified props/value by using effects
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, LifeCycleTypes } from '@ifcloud-formily/react' 4 5const InputField = props => ( 6 <Field {...props}> 7 {({ state, mutators }) => { 8 const loading = state.props.loading 9 return ( 10 <React.Fragment> 11 {props.label && <label>{props.label}</label>} 12 {loading ? ( 13 ' loading... ' 14 ) : ( 15 <input 16 disabled={!state.editable} 17 value={state.value || ''} 18 onChange={mutators.change} 19 onBlur={mutators.blur} 20 onFocus={mutators.focus} 21 /> 22 )} 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 ) 27 }} 28 </Field> 29) 30 31const CheckedField = props => ( 32 <Field {...props}> 33 {({ state, mutators }) => { 34 const loading = state.props.loading 35 return ( 36 <React.Fragment> 37 {props.label && <label>{props.label}</label>} 38 {loading ? ( 39 ' loading... ' 40 ) : ( 41 <input 42 type="checkbox" 43 onChange={() => { 44 mutators.change(!state.value) 45 }} 46 checked={!!state.value} 47 /> 48 )} 49 <span style={{ color: 'red' }}>{state.errors}</span> 50 <span style={{ color: 'orange' }}>{state.warnings}</span> 51 </React.Fragment> 52 ) 53 }} 54 </Field> 55) 56 57const actions = createFormActions() 58const App = () => { 59 return ( 60 <Form 61 actions={actions} 62 effects={($, { setFieldState }) => { 63 $(LifeCycleTypes.ON_FORM_INIT).subscribe(() => { 64 setFieldState('a~', state => (state.visible = false)) 65 }) 66 67 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'trigger').subscribe( 68 triggerState => { 69 setFieldState('a~', state => { 70 state.visible = triggerState.value 71 }) 72 } 73 ) 74 75 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'a').subscribe(fieldState => { 76 setFieldState('a-copy', state => { 77 state.value = fieldState.value 78 }) 79 }) 80 }} 81 > 82 <CheckedField name="trigger" label="show/hide" /> 83 <div> 84 <InputField label="a" name="a" /> 85 </div> 86 <div> 87 <InputField label="a-copy" name="a-copy" /> 88 </div> 89 </Form> 90 ) 91} 92 93ReactDOM.render(<App />, document.getElementById('root'))
Example:Change dataSource in select asynchronously by effects
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, LifeCycleTypes } from '@ifcloud-formily/react' 4 5const InputField = props => ( 6 <Field {...props}> 7 {({ state, mutators }) => { 8 const loading = state.props.loading 9 return ( 10 <React.Fragment> 11 {props.label && <label>{props.label}</label>} 12 {loading ? ( 13 ' loading... ' 14 ) : ( 15 <input 16 disabled={!state.editable} 17 value={state.value || ''} 18 onChange={mutators.change} 19 onBlur={mutators.blur} 20 onFocus={mutators.focus} 21 /> 22 )} 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 ) 27 }} 28 </Field> 29) 30const CheckedField = props => ( 31 <Field {...props}> 32 {({ state, mutators }) => { 33 const loading = state.props.loading 34 return ( 35 <React.Fragment> 36 {props.label && <label>{props.label}</label>} 37 {loading ? ( 38 ' loading... ' 39 ) : ( 40 <input 41 type="checkbox" 42 onChange={() => { 43 mutators.change(!state.value) 44 }} 45 checked={!!state.value} 46 /> 47 )} 48 <span style={{ color: 'red' }}>{state.errors}</span> 49 <span style={{ color: 'orange' }}>{state.warnings}</span> 50 </React.Fragment> 51 ) 52 }} 53 </Field> 54) 55 56const SelectField = props => ( 57 <Field {...props}> 58 {({ state, mutators }) => { 59 const { loading, dataSource = [] } = state.props 60 return ( 61 <React.Fragment> 62 {props.label && <label>{props.label}</label>} 63 {loading ? ( 64 ' loading... ' 65 ) : ( 66 <select 67 disabled={!state.editable} 68 value={state.value || ''} 69 onChange={mutators.change} 70 onBlur={mutators.blur} 71 onFocus={mutators.focus} 72 > 73 {dataSource.map(item => ( 74 <option value={item.value}>{item.label}</option> 75 ))} 76 </select> 77 )} 78 <span style={{ color: 'red' }}>{state.errors}</span> 79 <span style={{ color: 'orange' }}>{state.warnings}</span> 80 </React.Fragment> 81 ) 82 }} 83 </Field> 84) 85 86const actions = createFormActions() 87const App = () => { 88 return ( 89 <Form 90 actions={actions} 91 effects={($, { setFieldState }) => { 92 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'trigger').subscribe( 93 fieldState => { 94 const dataSource = [ 95 { label: 'aa', value: 'aa' }, 96 { label: 'bb', value: 'bb' } 97 ] 98 setFieldState('sync-source', state => { 99 state.props.dataSource = fieldState.value ? dataSource : [] 100 }) 101 setFieldState('async-source', state => { 102 state.props.loading = true 103 }) 104 105 setTimeout(() => { 106 setFieldState('async-source', state => { 107 state.props.loading = false 108 state.props.dataSource = fieldState.value ? dataSource : [] 109 }) 110 }, 300) 111 } 112 ) 113 }} 114 > 115 <CheckedField name="trigger" label="show/reset dataSource" /> 116 <div> 117 <SelectField label="sync-source" name="sync-source" /> 118 </div> 119 <div> 120 <SelectField label="async-source" name="async-source" /> 121 </div> 122 </Form> 123 ) 124} 125 126ReactDOM.render(<App />, document.getElementById('root'))
Example:validation when form mounted and re-trigger validation when field change
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, LifeCycleTypes } from '@ifcloud-formily/react' 4 5const InputField = props => ( 6 <Field {...props}> 7 {({ state, mutators }) => { 8 const loading = state.props.loading 9 return ( 10 <React.Fragment> 11 {props.label && <label>{props.label}</label>} 12 {loading ? ( 13 ' loading... ' 14 ) : ( 15 <input 16 disabled={!state.editable} 17 value={state.value || ''} 18 onChange={mutators.change} 19 onBlur={mutators.blur} 20 onFocus={mutators.focus} 21 /> 22 )} 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 ) 27 }} 28 </Field> 29) 30 31const actions = createFormActions() 32const App = () => { 33 return ( 34 <Form 35 actions={actions} 36 effects={($, { validate, setFieldState }) => { 37 $(LifeCycleTypes.ON_FORM_MOUNT).subscribe(() => { 38 validate() 39 }) 40 41 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'a').subscribe(fieldState => { 42 setFieldState('a-copy', state => { 43 state.value = fieldState.value 44 }) 45 }) 46 }} 47 > 48 <InputField label="a" name="a" /> 49 <div> 50 <InputField label="a-copy" name="a-copy" required /> 51 </div> 52 </Form> 53 ) 54} 55 56ReactDOM.render(<App />, document.getElementById('root'))
Example:See how ArrayField communicate with other field by using effects
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, LifeCycleTypes } from '@ifcloud-formily/react' 4 5const InputField = props => ( 6 <Field {...props}> 7 {({ state, mutators }) => { 8 const loading = state.props.loading 9 return ( 10 <React.Fragment> 11 {props.label && <label>{props.label}</label>} 12 {loading ? ( 13 ' loading... ' 14 ) : ( 15 <input 16 disabled={!state.editable} 17 value={state.value || ''} 18 onChange={mutators.change} 19 onBlur={mutators.blur} 20 onFocus={mutators.focus} 21 /> 22 )} 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 ) 27 }} 28 </Field> 29) 30 31const actions = createFormActions() 32const App = () => { 33 return ( 34 <Form 35 actions={actions} 36 effects={($, { validate, setFieldState }) => { 37 $(LifeCycleTypes.ON_FORM_INIT).subscribe(() => { 38 setFieldState('userList.*.username', state => { 39 state.visible = false 40 }) 41 }) 42 43 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'trigger').subscribe( 44 fieldState => { 45 setFieldState('userList.*.username', state => { 46 state.visible = fieldState.value 47 }) 48 } 49 ) 50 }} 51 > 52 <div> 53 <Field name="trigger" label="show/hide username"> 54 {({ state, mutators }) => { 55 return ( 56 <input 57 type="checkbox" 58 onChange={mutators.change} 59 checked={state.value ? 'checked' : undefined} 60 /> 61 ) 62 }} 63 </Field> 64 </div> 65 <div> 66 <Field 67 initialValue={[ 68 { username: 'bobby', age: 22 }, 69 { username: 'lily', age: 21 } 70 ]} 71 name="userList" 72 > 73 {({ state, mutators }) => { 74 return ( 75 <React.Fragment> 76 {state.value.map((item, index) => { 77 return ( 78 <div key={index}> 79 <Field name={`userList[${index}]`} initialValue={{}}> 80 {({ state: innerState, mutators: innerMutator }) => { 81 return ( 82 <React.Fragment> 83 {Object.keys(innerState.value).map(key => { 84 if (!innerMutator.exist(key)) return 85 return ( 86 <React.Fragment key={key}> 87 <InputField 88 label={key} 89 name={`userList[${index}].${key}`} 90 /> 91 </React.Fragment> 92 ) 93 })} 94 <button 95 onClick={() => { 96 innerMutator.change({ 97 ...innerState.value, 98 [new Date().getTime()]: new Date().getTime() 99 }) 100 }} 101 > 102 + 103 </button> 104 </React.Fragment> 105 ) 106 }} 107 </Field> 108 109 <button onClick={() => mutators.remove(index)}> 110 Remove 111 </button> 112 </div> 113 ) 114 })} 115 <button 116 onClick={() => 117 mutators.push({ 118 username: undefined, 119 age: undefined 120 }) 121 } 122 > 123 Add Item 124 </button> 125 <button 126 onClick={() => 127 console.log(actions.getFormState(state => state.values)) 128 } 129 > 130 print 131 </button> 132 </React.Fragment> 133 ) 134 }} 135 </Field> 136 </div> 137 </Form> 138 ) 139} 140 141ReactDOM.render(<App />, document.getElementById('root'))
Make your own reusable effects.
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, FormEffectHooks } from '@ifcloud-formily/react' 4 5const InputField = props => ( 6 <Field {...props}> 7 {({ state, mutators }) => { 8 const loading = state.props.loading 9 return ( 10 <React.Fragment> 11 {props.label && <label>{props.label}</label>} 12 {loading ? ( 13 ' loading... ' 14 ) : ( 15 <input 16 disabled={!state.editable} 17 value={state.value || ''} 18 onChange={mutators.change} 19 onBlur={mutators.blur} 20 onFocus={mutators.focus} 21 /> 22 )} 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 ) 27 }} 28 </Field> 29) 30const CheckedField = props => ( 31 <Field {...props}> 32 {({ state, mutators }) => { 33 const loading = state.props.loading 34 return ( 35 <React.Fragment> 36 {props.label && <label>{props.label}</label>} 37 {loading ? ( 38 ' loading... ' 39 ) : ( 40 <input 41 type="checkbox" 42 onChange={() => { 43 mutators.change(!state.value) 44 }} 45 checked={!!state.value} 46 /> 47 )} 48 <span style={{ color: 'red' }}>{state.errors}</span> 49 <span style={{ color: 'orange' }}>{state.warnings}</span> 50 </React.Fragment> 51 ) 52 }} 53 </Field> 54) 55 56const { onFormMount$, onFieldValueChange$ } = FormEffectHooks 57const getEffects = () => { 58 const actions = createFormActions() 59 onFormMount$().subscribe(() => { 60 actions.setFieldState('a~', state => (state.visible = false)) 61 }) 62 63 onFieldValueChange$('trigger').subscribe(triggerState => { 64 actions.setFieldState('a~', state => { 65 state.visible = triggerState.value 66 }) 67 }) 68 69 onFieldValueChange$('a').subscribe(fieldState => { 70 actions.setFieldState('a-copy', state => { 71 state.value = fieldState.value 72 }) 73 }) 74} 75 76const actions = createFormActions() 77const App = () => { 78 return ( 79 <Form 80 actions={actions} 81 effects={() => { 82 getEffects() 83 }} 84 > 85 <CheckedField name="trigger" label="show/hide" /> 86 <div> 87 <InputField label="a" name="a" /> 88 </div> 89 <div> 90 <InputField label="a-copy" name="a-copy" /> 91 </div> 92 </Form> 93 ) 94} 95 96ReactDOM.render(<App />, document.getElementById('root'))
Example:Combo value of username and age. Check FormSpy for more inforation.
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, FormSpy } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const App = () => { 25 return ( 26 <Form actions={actions}> 27 <label>username</label> 28 <InputField name="username" /> 29 <label>age</label> 30 <InputField name="age" /> 31 <FormSpy> 32 {({ state, form }) => { 33 return ( 34 <div> 35 name: {form.getFieldValue('username')} 36 <br /> 37 age: {form.getFieldValue('age')} 38 </div> 39 ) 40 }} 41 </FormSpy> 42 </Form> 43 ) 44} 45 46ReactDOM.render(<App />, document.getElementById('root'))
1Dictionary 2--app 3 |---components 4 |---customForm
Example:Cross-file consumption form state, Check FormProvider and FormSpy for more information.
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 createFormActions, 7 FormSpy, 8 FormProvider 9} from '@ifcloud-formily/react' 10 11const actions = createFormActions() 12const InputField = props => ( 13 <Field {...props}> 14 {({ state, mutators }) => ( 15 <React.Fragment> 16 <input 17 disabled={!state.editable} 18 value={state.value || ''} 19 onChange={mutators.change} 20 onBlur={mutators.blur} 21 onFocus={mutators.focus} 22 /> 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 )} 27 </Field> 28) 29 30const CustomForm = () => { 31 return ( 32 <Form actions={actions}> 33 <label>username</label> 34 <InputField name="username" /> 35 <label>age</label> 36 <InputField name="age" /> 37 </Form> 38 ) 39} 40 41const App = () => { 42 return ( 43 <FormProvider> 44 <CustomForm /> 45 <FormSpy> 46 {({ state, form }) => { 47 return ( 48 <div> 49 name: {form.getFieldValue('username')} 50 <br /> 51 age: {form.getFieldValue('age')} 52 </div> 53 ) 54 }} 55 </FormSpy> 56 </FormProvider> 57 ) 58} 59 60ReactDOM.render(<App />, document.getElementById('root'))
1import React, { useState } from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 createFormActions, 7 FormSpy, 8 FormPath 9} from '@ifcloud-formily/react' 10 11const actions = createFormActions() 12 13const App = () => { 14 return ( 15 <Form actions={actions}> 16 <label>range input</label> 17 <Field name="[start,end]"> 18 {({ state, mutators }) => { 19 const [start, end] = state.value 20 return ( 21 <div> 22 <label>start</label> 23 <input 24 value={start} 25 onChange={e => { 26 mutators.change([e.target.value, end]) 27 }} 28 /> 29 <label>end</label> 30 <input 31 value={end} 32 onChange={e => { 33 mutators.change([start, e.target.value]) 34 }} 35 /> 36 </div> 37 ) 38 }} 39 </Field> 40 <button 41 onClick={() => { 42 actions.setFormState(state => { 43 state.values = { start: 'x', end: 'y' } 44 }) 45 }} 46 > 47 set value 48 </button> 49 <FormSpy> 50 {({ state, form }) => { 51 return ( 52 <div> 53 Form values: 54 <code> 55 <pre> 56 {JSON.stringify( 57 form.getFormState(state => state.values), 58 null, 59 2 60 )} 61 </pre> 62 </code> 63 </div> 64 ) 65 }} 66 </FormSpy> 67 </Form> 68 ) 69} 70 71ReactDOM.render(<App />, document.getElementById('root'))
1import React, { useState } from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 createFormActions, 7 FormSpy, 8 FormPath 9} from '@ifcloud-formily/react' 10 11const actions = createFormActions() 12const InputField = props => ( 13 <Field {...props}> 14 {({ state, mutators }) => { 15 const loading = state.props.loading 16 return ( 17 <React.Fragment> 18 {props.label && <label>{props.label}</label>} 19 {loading ? ( 20 ' loading... ' 21 ) : ( 22 <input 23 disabled={!state.editable} 24 value={state.value || ''} 25 onChange={mutators.change} 26 onBlur={mutators.blur} 27 onFocus={mutators.focus} 28 /> 29 )} 30 <span style={{ color: 'red' }}>{state.errors}</span> 31 <span style={{ color: 'orange' }}>{state.warnings}</span> 32 </React.Fragment> 33 ) 34 }} 35 </Field> 36) 37 38const App = () => { 39 return ( 40 <Form actions={actions}> 41 <Field name="{aa:{bb:{cc:destructor1,dd:[destructor2,destructor3],ee}}}"> 42 {({ state, mutators }) => { 43 return ( 44 <div> 45 <button 46 onClick={() => { 47 mutators.change({ 48 aa: { 49 bb: { 50 cc: 123, 51 dd: [333, 444], 52 ee: 'abcde' 53 } 54 } 55 }) 56 }} 57 > 58 set value 59 </button> 60 <div>Field value:</div> 61 <code> 62 <pre>{JSON.stringify(state.value, null, 2)}</pre> 63 </code> 64 </div> 65 ) 66 }} 67 </Field> 68 <button 69 onClick={() => { 70 actions.setFieldState( 71 FormPath.match( 72 '[[{aa:{bb:{cc:destructor1,dd:\\[destructor2,destructor3\\],ee}}}]]' 73 ), 74 state => { 75 state.value = { 76 aa: { 77 bb: { 78 cc: 'a', 79 dd: ['b', 'c'], 80 ee: 'd' 81 } 82 } 83 } 84 } 85 ) 86 }} 87 > 88 outside set 89 </button> 90 <FormSpy> 91 {({ state, form }) => { 92 return ( 93 <div> 94 Form values: 95 <code> 96 <pre> 97 {JSON.stringify( 98 form.getFormState(state => state.values), 99 null, 100 2 101 )} 102 </pre> 103 </code> 104 </div> 105 ) 106 }} 107 </FormSpy> 108 </Form> 109 ) 110} 111 112ReactDOM.render(<App />, document.getElementById('root'))
<Form/>
<Form>
Props
1interface IFormProps { 2 // Form value 3 value?: any 4 defaultValue?: any // Form initial value 5 initialValues?: any 6 // formAPI 7 actions?: IFormActions | IFormAsyncActions 8 // effect 9 effects?: IFormEffect<any, IFormActions | IFormAsyncActions> 10 // IForm instance 11 form?: IForm // Form change event callback 12 onChange?: (values: Value) => void // Form submission event callback 13 onSubmit?: (values: Value) => void | Promise<Value> // Form reset event callback 14 onReset?: () => void // Form verification failure event callback 15 onValidateFailed?: (valideted: IFormValidateResult) => void 16 children?: React.ReactElement | ((form: IForm) => React.ReactElement) 17 // Whether to use the dirty check, the default will go immer accurate update 18 useDirty?: boolean 19 // Is it editable, overall control in the Form dimension 20 editable?: boolean 21 // Whether to go pessimistic check, stop the subsequent check when the first check fails 22 validateFirst?: boolean 23}
<Field/>
<Field>
Props
1interface IFieldStateUIProps { 2 // Node path 3 path?: FormPathPattern // Node path 4 nodePath?: FormPathPattern // Data path 5 dataPath?: FormPathPattern // Data path 6 name?: string // Field value, is equal to values[0] 7 value?: any // Field multi-parameter value, such as when the field onChange trigger, the event callback passed multi-parameter data, then the value of all parameters will be stored here 8 values?: any[] // Initial value 9 10 initialValue?: any // field extension properties 11 visible?: boolean //Field initial visible status(Whether the data and style is visible) 12 display?: boolean //Field initial display status(Whether the style is visible) 13 props?: FieldProps // Check the rules, the specific type description refers to the following documents 14 rules?: ValidatePatternRules[] // Is it required? 15 required?: boolean // Is it editable? 16 editable?: boolean // Whether to use the dirty check, the default will go immer accurate update 17 useDirty?: boolean 18 // Field state calculation container, mainly used to extend the core linkage rules 19 computeState?: (draft: IFieldState, prevState: IFieldState) => void 20 // type of trigger validation 21 triggerType?: 'onChange' | 'onBlur' 22 // get value from browser event(eg. e.target.value) 23 getValueFromEvent?: (...args: any[]) => any 24 children?: React.ReactElement | ((api: IFieldAPI) => React.ReactElement) 25}
Usage
Example:All type of field
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const App = () => { 25 return ( 26 <Form actions={actions}> 27 <div> 28 <h5>Basic Field</h5> 29 <Field name="id"> 30 {({ state, mutator }) => { 31 return <input value={state.value} onChange={mutator} /> 32 }} 33 </Field> 34 </div> 35 36 <div> 37 <h5>Object Field</h5> 38 <Field 39 name="user" 40 initialValue={{ 41 username: undefined, 42 age: undefined 43 }} 44 > 45 {({ state, mutators }) => { 46 return ( 47 <React.Fragment> 48 {Object.keys(state.value).map(key => { 49 if (!mutators.exist(key)) return 50 51 return ( 52 <div key={key}> 53 <span>{key}</span> 54 <InputField name={`user.${key}`} /> 55 <button 56 onClick={() => { 57 mutators.remove(key) 58 }} 59 > 60 x 61 </button> 62 </div> 63 ) 64 })} 65 <button 66 onClick={() => { 67 mutators.change({ 68 ...state.value, 69 [new Date().getTime()]: new Date().getTime() 70 }) 71 }} 72 > 73 + 74 </button> 75 </React.Fragment> 76 ) 77 }} 78 </Field> 79 </div> 80 81 <div> 82 <h5>ArrayField Field</h5> 83 <Field name="idList" initialValue={['1', '2', '3']}> 84 {({ state, mutators }) => { 85 return ( 86 <React.Fragment> 87 {state.value.map((item, index) => { 88 return ( 89 <div key={index}> 90 <InputField name={`idList[${index}]`} /> 91 <button onClick={() => mutators.remove(index)}> 92 Remove 93 </button> 94 </div> 95 ) 96 })} 97 <button onClick={() => mutators.push()}>Add Item</button> 98 </React.Fragment> 99 ) 100 }} 101 </Field> 102 </div> 103 104 <div> 105 <h5>ArrayObject Field</h5> 106 <Field 107 name="userList" 108 initialValue={[ 109 { username: 'bobby', age: 21 }, 110 { username: 'lily', age: 20 } 111 ]} 112 > 113 {({ state, mutators }) => { 114 return ( 115 <React.Fragment> 116 {state.value.map((item, index) => { 117 return ( 118 <div key={index}> 119 <Field name={`userList[${index}]`} initialValue={{}}> 120 {({ state: innerState, mutators: innerMutator }) => { 121 return ( 122 <React.Fragment> 123 {Object.keys(innerState.value).map(key => { 124 if (!innerMutator.exist(key)) return 125 return ( 126 <React.Fragment key={key}> 127 <InputField 128 name={`userList[${index}].${key}`} 129 /> 130 <button 131 onClick={() => { 132 innerMutator.remove(key) 133 }} 134 > 135 x 136 </button> 137 </React.Fragment> 138 ) 139 })} 140 <button 141 onClick={() => { 142 innerMutator.change({ 143 ...innerState.value, 144 [new Date().getTime()]: new Date().getTime() 145 }) 146 }} 147 > 148 + 149 </button> 150 </React.Fragment> 151 ) 152 }} 153 </Field> 154 155 <button onClick={() => mutators.remove(index)}> 156 Remove 157 </button> 158 </div> 159 ) 160 })} 161 <button 162 onClick={() => 163 mutators.push({ 164 username: undefined, 165 age: undefined 166 }) 167 } 168 > 169 Add Item 170 </button> 171 </React.Fragment> 172 ) 173 }} 174 </Field> 175 </div> 176 <button 177 onClick={() => console.log(actions.getFormState(state => state.values))} 178 > 179 print 180 </button> 181 </Form> 182 ) 183} 184 185ReactDOM.render(<App />, document.getElementById('root'))
<VirtualField/>
<VirtualField>
Props
1interface IVirtualFieldProps { 2 // Node path 3 path?: FormPathPattern // Node path 4 nodePath?: FormPathPattern // Data path 5 dataPath?: FormPathPattern // Data path 6 visible?: boolean //Field initial visible status(Whether the data and style is visible) 7 display?: boolean //Field initial display status(Whether the style is visible) 8 name?: string // Form extension properties 9 props?: FieldProps // Whether to use the dirty check, the default will go immer accurate update 10 useDirty?: boolean 11 // Field state calculation container, mainly used to extend the core linkage rules 12 computeState?: (draft: IFieldState, prevState: IFieldState) => void 13 children?: React.ReactElement | ((api: IFieldAPI) => React.ReactElement) 14}
Usage
Example:Setting <Layout>
size from 100x100 to 200x200
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, VirtualField } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const Layout = ({ children, width = '100px', height = '100px' }) => { 25 return ( 26 <div style={{ border: '1px solid #999', width, height }}>{children}</div> 27 ) 28} 29 30const App = () => { 31 return ( 32 <Form actions={actions}> 33 <Field name="user" initialValue={{}}> 34 {({ state, mutator }) => { 35 return ( 36 <VirtualField name="user.layout"> 37 {({ state: layoutState }) => { 38 return ( 39 <Layout 40 width={layoutState.props.width} 41 height={layoutState.props.height} 42 > 43 <label>username</label> 44 <InputField name="username" /> 45 <label>age</label> 46 <InputField name="age" /> 47 </Layout> 48 ) 49 }} 50 </VirtualField> 51 ) 52 }} 53 </Field> 54 55 <button 56 onClick={() => { 57 // some where dynamic change layout's props 58 actions.setFieldState('user.layout', state => { 59 state.props.width = '200px' 60 state.props.height = '200px' 61 }) 62 }} 63 > 64 change layout 65 </button> 66 </Form> 67 ) 68} 69 70ReactDOM.render(<App />, document.getElementById('root'))
<FormSpy/>
<FormSpy>
Props
1interface IFormSpyProps { 2 // selector, eg: [ LifeCycleTypes.ON_FORM_SUBMIT_START, LifeCycleTypes.ON_FORM_SUBMIT_END ] 3 selector?: string[] | string 4 // reducer 5 reducer?: ( 6 state: any, 7 action: { type: string; payload: any }, 8 form: IForm 9 ) => any 10 children?: React.ReactElement | ((api: IFormSpyAPI) => React.ReactElement) 11}
Usage
Example1: Form state change counter
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 createFormActions, 7 FormSpy, 8 LifeCycleTypes 9} from '@ifcloud-formily/react' 10 11const actions = createFormActions() 12const InputField = props => ( 13 <Field {...props}> 14 {({ state, mutators }) => ( 15 <React.Fragment> 16 <input 17 disabled={!state.editable} 18 value={state.value || ''} 19 onChange={mutators.change} 20 onBlur={mutators.blur} 21 onFocus={mutators.focus} 22 /> 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 )} 27 </Field> 28) 29 30const App = () => { 31 return ( 32 <Form actions={actions}> 33 <label>username</label> 34 <InputField name="username" /> 35 <label>age</label> 36 <InputField name="age" /> 37 <FormSpy 38 selector={LifeCycleTypes.ON_FORM_VALUES_CHANGE} 39 reducer={(state, action, form) => ({ 40 count: state.count ? state.count + 1 : 1 41 })} 42 > 43 {({ state, type, form }) => { 44 return <div>count: {state.count || 0}</div> 45 }} 46 </FormSpy> 47 </Form> 48 ) 49} 50 51ReactDOM.render(<App />, document.getElementById('root'))
Example2:Combo
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { Form, Field, createFormActions, FormSpy } from '@ifcloud-formily/react' 4 5const actions = createFormActions() 6const InputField = props => ( 7 <Field {...props}> 8 {({ state, mutators }) => ( 9 <React.Fragment> 10 <input 11 disabled={!state.editable} 12 value={state.value || ''} 13 onChange={mutators.change} 14 onBlur={mutators.blur} 15 onFocus={mutators.focus} 16 /> 17 <span style={{ color: 'red' }}>{state.errors}</span> 18 <span style={{ color: 'orange' }}>{state.warnings}</span> 19 </React.Fragment> 20 )} 21 </Field> 22) 23 24const App = () => { 25 return ( 26 <Form actions={actions}> 27 <label>username</label> 28 <InputField name="username" /> 29 <label>age</label> 30 <InputField name="age" /> 31 <FormSpy> 32 {({ state, form }) => { 33 return ( 34 <div> 35 name: {form.getFieldValue('username')} 36 <br /> 37 age: {form.getFieldValue('age')} 38 </div> 39 ) 40 }} 41 </FormSpy> 42 </Form> 43 ) 44} 45 46ReactDOM.render(<App />, document.getElementById('root'))
<FormProvider/>
Used with FormSpy, often used in Cross-file consumption form state
Usage
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 createFormActions, 7 FormSpy, 8 FormProvider 9} from '@ifcloud-formily/react' 10 11const actions = createFormActions() 12const InputField = props => ( 13 <Field {...props}> 14 {({ state, mutators }) => ( 15 <React.Fragment> 16 <input 17 disabled={!state.editable} 18 value={state.value || ''} 19 onChange={mutators.change} 20 onBlur={mutators.blur} 21 onFocus={mutators.focus} 22 /> 23 <span style={{ color: 'red' }}>{state.errors}</span> 24 <span style={{ color: 'orange' }}>{state.warnings}</span> 25 </React.Fragment> 26 )} 27 </Field> 28) 29 30const CustomForm = () => { 31 return ( 32 <Form actions={actions}> 33 <label>username</label> 34 <InputField name="username" /> 35 <label>age</label> 36 <InputField name="age" /> 37 </Form> 38 ) 39} 40 41const App = () => { 42 return ( 43 <FormProvider> 44 <CustomForm /> 45 <FormSpy> 46 {({ state, form }) => { 47 return ( 48 <div> 49 name: {form.getFieldValue('username')} 50 <br /> 51 age: {form.getFieldValue('age')} 52 </div> 53 ) 54 }} 55 </FormSpy> 56 </FormProvider> 57 ) 58} 59 60ReactDOM.render(<App />, document.getElementById('root'))
<FormConsumer/>(deprecated,pls using <FormSpy/>)
<FormConsumer>
Props
1interface IFormConsumerProps { 2 // eg.[ LifeCycleTypes.ON_FORM_SUBMIT_START, LifeCycleTypes.ON_FORM_SUBMIT_END ] 3 selector?: string[] | string 4 children?: 5 | React.ReactElement 6 | ((api: IFormConsumerAPI) => React.ReactElement) 7}
useFormEffects
Implement local effects by using useFormEffects. Same effect as the example of Linkage Note: The life cycle of the listener starts from
ON_FORM_MOUNT
Signature
1(effects: IFormEffect): void
1import React from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 createFormActions, 7 useFormEffects, 8 LifeCycleTypes 9} from '@ifcloud-formily/react' 10 11const actions = createFormActions() 12const InputField = props => ( 13 <Field {...props}> 14 {({ state, mutators }) => { 15 const loading = state.props.loading 16 return ( 17 <React.Fragment> 18 {props.label && <label>{props.label}</label>} 19 {loading ? ( 20 ' loading... ' 21 ) : ( 22 <input 23 disabled={!state.editable} 24 value={state.value || ''} 25 onChange={mutators.change} 26 onBlur={mutators.blur} 27 onFocus={mutators.focus} 28 /> 29 )} 30 <span style={{ color: 'red' }}>{state.errors}</span> 31 <span style={{ color: 'orange' }}>{state.warnings}</span> 32 </React.Fragment> 33 ) 34 }} 35 </Field> 36) 37 38const CheckedField = props => ( 39 <Field {...props}> 40 {({ state, mutators }) => { 41 const loading = state.props.loading 42 return ( 43 <React.Fragment> 44 {props.label && <label>{props.label}</label>} 45 {loading ? ( 46 ' loading... ' 47 ) : ( 48 <input 49 type="checkbox" 50 onChange={() => { 51 mutators.change(!state.value) 52 }} 53 checked={!!state.value} 54 /> 55 )} 56 <span style={{ color: 'red' }}>{state.errors}</span> 57 <span style={{ color: 'orange' }}>{state.warnings}</span> 58 </React.Fragment> 59 ) 60 }} 61 </Field> 62) 63 64const FormFragment = () => { 65 useFormEffects(($, { setFieldState }) => { 66 $(LifeCycleTypes.ON_FORM_INIT).subscribe(() => { 67 setFieldState('a~', state => (state.visible = false)) 68 }) 69 70 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'trigger').subscribe( 71 triggerState => { 72 setFieldState('a~', state => { 73 state.visible = triggerState.value 74 }) 75 } 76 ) 77 78 $(LifeCycleTypes.ON_FIELD_VALUE_CHANGE, 'a').subscribe(fieldState => { 79 setFieldState('a-copy', state => { 80 state.value = fieldState.value 81 }) 82 }) 83 }) 84 85 return ( 86 <React.Fragment> 87 <CheckedField name="trigger" label="show/hide" /> 88 <div> 89 <InputField label="a" name="a" /> 90 </div> 91 <div> 92 <InputField label="a-copy" name="a-copy" /> 93 </div> 94 </React.Fragment> 95 ) 96} 97 98const App = () => { 99 return ( 100 <Form actions={actions}> 101 <FormFragment /> 102 </Form> 103 ) 104} 105 106ReactDOM.render(<App />, document.getElementById('root'))
useFormState
使用 useFormState 为自定义组件提供 FormState 扩展和管理能力
签名
1(defaultState: T): [state: IFormState, setFormState: (state?: IFormState) => void]
用法
1import React, { useRef } from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 VirtualField, 7 createFormActions, 8 createEffectHook, 9 useForm, 10 useFormState, 11 useFormEffects, 12 useFieldState, 13 LifeCycleTypes 14} from '@ifcloud-formily/react' 15 16const InputField = props => ( 17 <Field {...props}> 18 {({ state, mutators }) => { 19 const loading = state.props.loading 20 return ( 21 <React.Fragment> 22 {props.label && <label>{props.label}</label>} 23 {loading ? ( 24 ' loading... ' 25 ) : ( 26 <input 27 disabled={!state.editable} 28 value={state.value || ''} 29 onChange={mutators.change} 30 onBlur={mutators.blur} 31 onFocus={mutators.focus} 32 /> 33 )} 34 <span style={{ color: 'red' }}>{state.errors}</span> 35 <span style={{ color: 'orange' }}>{state.warnings}</span> 36 </React.Fragment> 37 ) 38 }} 39 </Field> 40) 41 42const actions = createFormActions() 43const FormFragment = props => { 44 const [formState, setFormState] = useFormState({ extendVar: 0 }) 45 const { extendVar } = formState 46 47 return ( 48 <div> 49 <button 50 onClick={() => { 51 setFormState({ extendVar: extendVar + 1 }) 52 }} 53 > 54 add 55 </button> 56 <div>count: {extendVar}</div> 57 </div> 58 ) 59} 60 61const App = () => { 62 return ( 63 <Form actions={actions}> 64 <FormFragment /> 65 </Form> 66 ) 67} 68 69ReactDOM.render(<App />, document.getElementById('root'))
useFieldState
Manage state of custom field by using
useFieldState
Signature
1(defaultState: T): [state: IFieldState, setFieldState: (state?: IFieldState) => void]
1import React, { useRef } from 'react' 2import ReactDOM from 'react-dom' 3import { 4 Form, 5 Field, 6 VirtualField, 7 createFormActions, 8 createEffectHook, 9 useForm, 10 useFormEffects, 11 useFieldState, 12 LifeCycleTypes 13} from '@ifcloud-formily/react' 14 15const InputField = props => ( 16 <Field {...props}> 17 {({ state, mutators }) => { 18 const loading = state.props.loading 19 return ( 20 <React.Fragment> 21 {props.label && <label>{props.label}</label>} 22 {loading ? ( 23 ' loading... ' 24 ) : ( 25 <input 26 disabled={!state.editable} 27 value={state.value || ''} 28 onChange={mutators.change} 29 onBlur={mutators.blur} 30 onFocus={mutators.focus} 31 /> 32 )} 33 <span style={{ color: 'red' }}>{state.errors}</span> 34 <span style={{ color: 'orange' }}>{state.warnings}</span> 35 </React.Fragment> 36 ) 37 }} 38 </Field> 39) 40 41const changeTab$ = createEffectHook('changeTab') 42const actions = createFormActions() 43const TabFragment = props => { 44 const [fieldState, setLocalFieldState] = useFieldState({ current: 0 }) 45 const { current } = fieldState 46 const { children, dataSource, form } = props 47 const ref = useRef(current) 48 49 const update = cur => { 50 form.notify('changeTab', cur) 51 setLocalFieldState({ 52 current: cur 53 }) 54 } 55 56 useFormEffects(($, { setFieldState }) => { 57 dataSource.forEach((item, itemIdx) => { 58 setFieldState(item.name, state => { 59 state.display = itemIdx === current 60 }) 61 }) 62 63 changeTab$().subscribe(idx => { 64 dataSource.forEach((item, itemIdx) => { 65 setFieldState(item.name, state => { 66 state.display = itemIdx === idx 67 }) 68 }) 69 }) 70 }) 71 72 ref.current = current 73 const btns = dataSource.map((item, idx) => { 74 console.log('current', current, ref.current) 75 const focusStyle = 76 idx === current ? { color: '#fff', background: 'blue' } : {} 77 return ( 78 <button 79 style={focusStyle} 80 onClick={() => { 81 update(idx) 82 }} 83 > 84 {item.label} 85 </button> 86 ) 87 }) 88 89 return btns 90} 91 92const FormTab = props => { 93 return ( 94 <VirtualField name="layout_tab"> 95 {({ form }) => { 96 return <TabFragment {...props} form={form} /> 97 }} 98 </VirtualField> 99 ) 100} 101 102const App = () => { 103 return ( 104 <Form actions={actions}> 105 <FormTab 106 dataSource={[ 107 { label: 'tab-1', name: 'username' }, 108 { label: 'tab-2', name: 'age' } 109 ]} 110 /> 111 <div> 112 <InputField name="username" label="username" /> 113 <InputField name="age" label="age" /> 114 </div> 115 </Form> 116 ) 117} 118 119ReactDOM.render(<App />, document.getElementById('root'))
get IForm instance
Signature
1type useForm = < 2 Value = any, 3 DefaultValue = any, 4 EffectPayload = any, 5 EffectAction = any 6>( 7 props: IFormProps<Value, DefaultValue, EffectPayload, EffectAction> 8) => IForm
Usage
1import { useForm } from '@ifcloud-formily/react' 2 3const FormFragment = () => { 4 const form = useForm() 5 return <div>{form.getFieldValue('username')}</div> 6}
get IFieldHook instance
Signature
1type useField = (options: IFieldStateUIProps): IFieldHook
Usage
1import { useField } from '@ifcloud-formily/react' 2 3const FormFragment = props => { 4 const { form, state, props: fieldProps, mutators } = useField({ 5 name: 'username' 6 }) 7 8 return ( 9 <input 10 {...fieldProps} 11 {...props} 12 value={state.value} 13 onChange={mutators.change} 14 /> 15 ) 16}
get IVirtualFieldHook instance
Signature
1type UseVirtualField = (options: IVirtualFieldStateProps): IVirtualFieldHook
Usage
1import { UseVirtualField } from '@ifcloud-formily/react' 2 3const FormFragment
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
10 commit(s) and 3 issue activity found in the last 90 days -- score normalized to 10
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 7/26 approved changesets -- score normalized to 2
Reason
detected GitHub workflow tokens with excessive permissions
Details
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
Reason
project is not fuzzed
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
97 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More