react-component / field-form Goto Github PK
View Code? Open in Web Editor NEW⚡️ React Performance First Form Component
Home Page: https://field-form.react-component.now.sh/
License: MIT License
⚡️ React Performance First Form Component
Home Page: https://field-form.react-component.now.sh/
License: MIT License
Hi, I started using this library and I found something weird happening to me, when I type just one letter in my input, for some reason, it runs against my rules and does not pass in my required rule, and that's wrong since I have 1 letter in my input. Also, why is it checking my rules every time I type something in my input? I don't need that, I can just validate when I submit the form.
Note: I'm using React Native
My screen component which holds the form:
const Login: FunctionComponent<{
navigation: StackNavigationProp<{}>
}> = ({ navigation }) => {
const { login } = useContext(UserContext)
const [form] = useForm()
navigation.setOptions({
title: 'Login'
})
const authenticate = () => {
form.validateFields().then(({ email, password }) => {
})
}
return (
<Screen>
<View style={[GlobalStyles.flex, GlobalStyles.alignCenter, GlobalStyles.justifyCenter]}>
<Image style={styles.image} source={require('../../../assets/black_logo.png')} />
<Form component={FormView} form={form}>
<Field name="email" rules={[{ required: true }]}>
<Input placeholder="Email" />
</Field>
<Field name="Password" rules={[{ required: true }]}>
<Input placeholder="Password" secureTextEntry={true} />
</Field>
</Form>
<Button type="primary" onPress={authenticate}>
ENTRAR
</Button>
</View>
</Screen>
)
}
My Field component:
const Field: FunctionComponent<{
} & FieldProps> = ({ children, ...props }) => {
return (
<FormField trigger="onChangeText" getValueFromEvent={text => text} {...props}>
{
(control, meta) => {
return <View>
{
React.cloneElement(children as any, { error: meta.errors.length > 0, ...control })
}
{
meta.errors.map((error, index) => (
<Error key={index}>
{error}
</Error>
))
}
</View>
}
}
</FormField>
)
}
And my Input component:
const Input: FunctionComponent<{
error?: boolean
} & TextInputProps> = ({ error, ...props }) => {
return (
<TextInput style={[styles.container, error ? styles.error : {}]} {...props} />
)
}
This only happens when you type the FIRST LETTER ONLY. When you type the second letter the error goes away, also if you have 2 letters and remove one letting the input value with 1 letter, the error doesn't show as well, so this only happens when the input is empty and you type one letter only.
有部分实际情况,input name属性和页面上看到的label是不同的,所以希望能替换为label
setValue
in valueUtil
use lodash/fp/set
to set value, this cause setValue
will not work as expect in some case
field-form/src/utils/valueUtil.ts
Lines 22 to 25 in c65e768
consider this situation, a variable named as a
, and it's initial value is a boolean
const initialValues = {
a: true
}
in the form field, a field name path is ['a', 'b']
, and field update, but in lodash/fp/set
, a
will be transformed by Object(value)
nested[key] = clone(index == lastIndex ? value : Object(value));
a
-> Boolean{true}
so setValue
will not work, a
will always be true
常用场景需要使用自定义组件, 组件为Form表单, 放在Field组件内使用, 外层表单校验时怎么触发子Form校验
我在antd(4.0) form中使用一个自定义组件, 该自定义组件每次加载会异步加载一些数据
const MeetingTab = ({ onChange, value = 0 }) => {
const [selectTab, setSelectTab] = useState<number>(value)
const [meetingRooms, setMeetingRooms] = useState<number[]>([])
const handleMettingTabChange = useCallback(
value => {
setSelectTab(value)
if (onChange) {
onChange(value)
}
},
[onChange]
)
useEffect(() => {
if (!meetingRooms.length) {
//异步请求
request().then(data => {
setMeetingRooms(data)
})
}
}, [meetingRooms])
const renderTab = useMemo(() => {
return meetingRooms.map((value, index) => {
const isActive = selectTab === value ? "active" : ""
return (
<li onClick={() => handleMettingTabChange(value)} key={index} className={isActive}>
{value}
</li>
)
})
}, [handleMettingTabChange, meetingRooms])
return <div>{renderTab}</div>
}
当使用form.resetFields时, 会导致该组件会重新加载一次, 导致多了一次请求!
当然通过props可以解决这一问题,但是我只想在组件里进行异步请求, 又不想在resetFields时再请求一次, 有什么好的办法吗?
Not that it is worth anything but I think the hook API would be better if we dropped the array. There is no rule that enforce a hook to return an array and in that case, an object would be better, as it would allow destructuring in a single line:
const {form, getFieldError} = Form.useForm();
Ideally form would only be a single ref without the extra API to keep things dry.
现在把某些自定义组件集成到form得用Field组件,如果有个useField hooks感觉会更加灵活:
const [ control, meta ] = useField({ name, form })
Line 590 in b970d90
returnPromise.catch
中间缺少空格?
import React from 'react';
import CssBaseline from '@material-ui/core/CssBaseline';
import TextField from '@material-ui/core/TextField';
import Grid from '@material-ui/core/Grid';
import { makeStyles } from '@material-ui/core/styles';
// import Button from '@material-ui/core/Button';
import Form, { Field } from 'rc-field-form';
const useStyles = makeStyles(theme => ({
gridContainer:{
margin: theme.spacing(2),
display:'flex',
flexWrap:'wrap',
flexDirection:'column',
alignItems:'center'
},
grid:{
margin: theme.spacing(2),
}
}));
export default function Login() {
const classes = useStyles();
return (
<React.Fragment>
<Form
// onFinish={v => {
// console.log(v);
// }}
initialValues={{
user:'hello',
pwd:'hello',
}}
>
<TextField
autoComplete
autoFocus
placeholder="初始帐号:hello"
required
label="帐号"
helperText="初始帐号:hello,该帐号仅提供浏览权限"
// multiline
margin="normal"
variant="outlined"
>
<TextField
autoComplete
autoFocus
placeholder="初始帐号:hello"
required
label="帐号"
helperText="初始帐号:hello,该帐号仅提供浏览权限"
// multiline
margin="normal"
variant="outlined"
>
submit
</React.Fragment>
)
}
目前 button 只能使用 带submit 属性的 自定义组件.. 打包后能获取到表单的数据。
在支持其他组件的扩展性上可以 再考虑下?
I can currently specify my own ValidatorMessages, but no way to provide extra keys for the message template string.
There is a option(additionalKv
) but it is not being used.
field-form/src/utils/validateUtil.ts
Lines 43 to 58 in c465860
regarding big change to form.getFieldsValue() and form.getFieldValues(true).
semver not respected. antd-rc5 takes a npm dependency using ^ on this in a tagged release and so now we have unpredictable builds and big behaviourable changes with regards to forms.
What is 0.0.0-rc6 meant to represent logically?
#versioning #semver #breaking
for example, my data is
[{a:1,b:1},{a,2,b:1}]
when I add another item (using operation.add
), the data turns to be
[{a:1,b:1},{a,2,b:1},undefined]
but in fact I need to pass a defaultValue instead of undefined
WHAT'S EXPECTED:
operation.add({a:1})
代码: <Form.Item name="name" label="姓名" rules={[{ required: true }]} >
提示: 应该显示姓名是必填字段,还是显示name 是必填字段。
在 Form.Item 的 children 中 封装自定义组件
在调用 form.resetFields
API 后
自定义组件中
React.useEffect(() => {
return () => {
console.log(1);
}
}, []);
会输出两次
<Form component={false} form={form}>
<List>
<Field name="day">
<InputItem />
</Field>
</List>
</Form>
调用form.setFieldsValue({day: '12'})
,并不能成功地给InputItem赋值。
但是如果给Form组件的initialValues={{day: '12'}},又是可以的。
I have a situation where I need to manually set the value of a form field, not as part of initialization, but as a result of a server API call. I was looking for something like setFieldValue
but I only see setFieldsValue
is available. Could you guide me on how to approach this situation? I would really like to avoid knowledge of the entire form state as I'm trying to implement reusable "sub-forms" which are not aware of which form they are part of, but they do need to be able to set/control the value for some of their fields.
For example, I have a dropdown in the form and based on dropdown item selected, I want to render different components/sub-form.
Warning: A component is changing an uncontrolled input of type undefined to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components
in input (at src/index.tsx:8)
in Input (at src/index.tsx:14)
in Field (at src/index.tsx:13)
in form (created by ForwardRef(Form))
in ForwardRef(Form) (at src/index.tsx:12)
in App (at src/index.tsx:21)
now I want to set value of name['children', 1, 'level']
to 'high', so i do like this,
const values = {};
lodash.set(values, ['children', 1, 'level'], 'high')
form.setFieldsValue(values);
but now values is {children: [undefined, {level: 'high'}]}, the children[0] is undefined, so I have no intention, but i changed children[0].
so i think you should think that name continues to support 'a.b.c' format, thank you.
I use setFields and I found the Field children rerender?
Is it appropriate?
What should I do to make it not rerender?
I'm trying to setup validation error state/messages and I can't find how to do it:
Looks like the <Field />
component does not pass any validation related prop to its children, (only value/onChange).
Using form.getFieldError
in the parent does not work as it's not properly called upon validation.
Haven't found a getFieldProps
API to extract validation statuses from the form instance.
Here is a quick code-sandbox: https://codesandbox.io/s/rc-field-form-5jcfm-5jcfm
I know this is alpha software, but it would be great to add some recipe.md file with common use case! Thanks for the great work.
createForm
receive an object like interface/type,makes stronger type checking and better field name IntelliSense
interface Param$Login {
username: string;
password: string;
}
const { Form, Field, useForm } = createForm<Param$Login>();
I have created a wrapper for this library with createForm
API. It would be great if this feature officially supported.
onFiledChange 每次都执行3次,设计如此吗?
when I use ant Upload Component prop fileList: Array<UploadFile>
as the initialValues of the form, the initial UploadFile[]
cannot be assign to StoreValue, because the only supported array is StoreBaseValue[]
, not Store[]
So we need to change the typescript interface to:
export declare type StoreValue = StoreBaseValue | Store | StoreBaseValue[] | Store[];
export interface Store {
[name: string]: StoreValue;
}
问题1:antd v3使用rc-form时,当因为逻辑分支导致被getFieldDecorator包裹的部分字段未被渲染时,原本保存在这些字段上的值会被清空,再次渲染时会使用initialValue上的值进行初始化;但v4使用rc-field-form时,未被渲染字段的值会持久保存,再次渲染时直接使用之前保存的值。这一行为不一致是刻意的还是bug?
v3版demo:https://codesandbox.io/s/kind-pare-2l760
v4版demo:https://codesandbox.io/s/dark-bush-gzv86
可以看到baz字段在两者间表现的不一致。
问题2:onFieldsChange回调api会在一次交互时触发2次,且第二次的changedFields参数为空数组,感觉是个bug?
Did not found a documented way to type the store values. Was expecting this API (what's used by react-hook-form):
type FormValues = {
email: string;
password: string;
};
const LoginForm: FunctionComponent<Props> = ({history}) => {
const [form] = Form.useForm<FormValues>();
However useForm
does not seem to accept a generic type.
Is there another way to type a form store or do you have another API in mind?
Is react-native supported or is it on the roadmap?
EDIT
: Looks like it's working just fine. And it's also specified in the README.md!
Guess you might want to add some examples at some point!
<Form
component={FormView}
onFinish={values => {
console.log('onFinish:', values);
}}
onFinishFailed={({values, errorFields, outOfDate}) => {
console.log('onFinishFailed:', {values, errorFields, outOfDate});
}}
>
<Field
name="username"
getValueFromEvent={({nativeEvent}) => {
return nativeEvent.text;
}}
rules={[{required: true}]}
>
<Input placeholder="Username" />
</Field>
</Form>
No major issues so far, had to tweak my FormView onSubmit call signature to add an event so that the preventDefault
calls do not fail.
What is the proper way to update the ith item value with rc-field-form?
Shouldn't onFinish
return all initialValues
even if they are not touched and no error? Here is example: https://codesandbox.io/s/busy-wozniak-pe2ec
Related with 9af332b
In https://github.com/react-component/field-form/blob/master/src/utils/messages.ts
The default message for, say, an invalid integer is '${name} is not a validate integer'.
It should be '${name} is not a valid integer'.
export interface ValidateErrorEntity {
values: Store;
errorFields: {
name: InternalNamePath;
errors: string[];
};
outOfDate: boolean;
}
export interface ValidateErrorEntity {
values: Store;
errorFields: Array<{
name: InternalNamePath;
errors: string[];
}>;
outOfDate: boolean;
}
Not that it is worth anything but I think the hook API would be better if we dropped the array. There is no rule that enforce a hook to return an array and in that case, an object would be better, as it would allow destructuring in a single line:
const {form, getFieldError} = Form.useForm();
Ideally form would only be a single ref without the extra API to keep things dry.
Is there any way to manually set the validation errors after server-side validation?
I have the case where I submit the data and the API is performing additional business-rules validation and return a list of errors for incorrect fields. atm there is no way to set the errors for fields
Thanks.
自定义封装 Form
Field
组件,在某个情况调用了 form.resetFields
, 所在组件的 useMemo
,useEffect
都穿透执行了😂
有什么好的解决办法吗
A common use case when building large forms is to only patch updated values, eg. the user only changed one or a few fields and you want to easily produce a PATCH
http request to apply the update on a backend. Without having to post the whole form payload every time.
Today grabbing these fields seems doable with isFieldTouched
but would be a PITA as it would require looping over every field & I haven't found an easy way to grab all current fields namePaths (would need a getFieldNamePaths
helper too).
Could gladly work on a PR if needed & it is something that you would consider.
Nested List Item seems to return React synthetic event as value instead of input value. For example
users[]
- 0
- fname (correct input value)
- lname (correct input value)
- friends
- fname (synthetic event as value)
Here is a simple repo case: https://codesandbox.io/s/boring-engelbart-fn0k7?fontsize=14&hidenavigation=1&theme=dark
<Form
ref={form => { this.form = form }}
style={{ overflow: 'auto' }}
name='global-feedback'
onFinish={this.onFinish}
onFinishFailed={this.onFinishFailed}
onFieldsChange={this.onFieldsChange}
initialValues={{
name: userInfo.name || userInfo.username,
email: userInfo.email
}}
>
After API push data to userInfo
, the form is still not reload ultil:
componentDidUpdate (prevProps, prevState, snapshot) {
if (this.form && prevState.userInfo.username !== this.state.userInfo.username) {
this.form.resetFields()
}
}
Any suggestion?
<Field name="username" label="用户" messageVariables={{ label: '用户名' }} />
因为我一个组件有多个规则,前面几个规则只是判断字符的规则,后面validator有一个异步的校验,是用来验重的,我想有没有办法,让前几个规则校验失败就不进行验重的校验了,目前好像设计是所有都会校验,并且统一返回错误的
for example, my data structure is:
{
a: 1,
b: 2,
c: 3,
}
I want to use Form.List
but I wouldn't transform structure in initialValues
and submit action.
I'd like to suggest that adding normalize
in Form.List
transform data structure into
user-defined field.
Lines 107 to 124 in bc56d70
children
of List
could get all values
from render
props
<List>
{(fields, values, operations) => (...)}
</List>
Line 352 in c65e768
I would very much want that the issue with constant Form re-rendering is addressed
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.