DouyinFE / semi-design

🚀A modern, comprehensive, flexible design system and React UI library. 🎨 Provide more than 3000+ Design Tokens, easy to build your design system. Make Semi Design to Any Design. 🧑🏻‍💻 Design to Code in one click
https://semi.design
Other
8.43k stars 711 forks source link

[Form] fromApi.setValue 校验状态异常 #1532

Closed HaceraI closed 1 year ago

HaceraI commented 1 year ago

Is there an existing issue for this?

Which Component

Form

Semi Version

2.31.2

Current Behavior

通过 fromApi.setValue 设置value时,校验状态未及时更新

https://user-images.githubusercontent.com/48341368/229446131-6dd66225-192d-48c5-a5cc-f3cecbd6027c.mp4

Expected Behavior

校验状态及时更新

Steps To Reproduce

No response

ReproducibleCode

import React from 'react';
import { Form, Tooltip } from '@douyinfe/semi-ui';
import { IconHelpCircle } from '@douyinfe/semi-icons';

() => {
    const { Option } = Form.Select;
    const api = useRef();

    const onGenClick = () => {
        api.current.setValue('Password', Math.random());
        // api.current.validate('Password'); // 无效
    }

    return (
        <Form layout='horizontal' onValueChange={values=>console.log(values)} getFormApi={formApi => api.current = formApi}>
            <Form.Input field='UserName' label='用户名' style={{ width: 80 }}/>
            <Form.Input
                field='Password'
                label={{ 
                    text: '密码',
                    extra: <Tooltip content='详情'><IconHelpCircle style={{ color: 'var(--semi-color-text-2)' }}/></Tooltip> 
                }}
                style={{ width: 176 }}
                rules={[{required: true, message: '请输入密码'}]}
                suffix={<span style={{ whiteSpace: 'nowrap', marginRight: '12px' }} onClick={onGenClick}>点击生成</span>}
            />
            <Form.Select field="Role" label={{ text: '角色', optional: true }} style={{ width: 176 }}>
                <Option value="admin">管理员</Option>
                <Option value="user">普通用户</Option>
                <Option value="guest">访客</Option>
            </Form.Select>
        </Form>
    );
};

Environment

- OS:
- browser:

Anything else?

https://semi.design/zh-CN/input/form

pointhalo commented 1 year ago

这个Demo的行为是符合预期的。

setValue 的作用仅在于 手动对 Field 赋值,手动赋值的情况下并不会触发 onChange事件,校验是与 onChange、onBlur之类的回调关联的,所以也并不会重新触发校验。 (对Form而言 ,Field都是受控组件。举Input 为例,对其setValue 等同于 更新 props.value,手动赋值时由于用户已经知道值是什么,是不应该触发 onChange的)


<input value={val} onChange={(e) => handleChange(e)} /> // 手动更新 props.val 不会触发 onChange

如果你希望手动复制后也执行校验,可以在 setValue 后手动执行 validate

formApi.setValue(field,  value);
formApi.validate([field]);
HaceraI commented 1 year ago

我明白了,感谢~

pointhalo commented 1 year ago

这个Demo的行为是符合预期的。

setValue 的作用仅在于 手动对 Field 赋值,手动赋值的情况下并不会触发 onChange事件,校验是与 onChange、onBlur之类的回调关联的,所以也并不会重新触发校验。 (对Form而言 ,Field都是受控组件。举Input 为例,对其setValue 等同于 更新 props.value,手动赋值时由于用户已经知道值是什么,是不应该触发 onChange的)


<input value={val} onChange={(e) => handleChange(e)} /> // 手动更新 props.val 不会触发 onChange

如果你希望手动复制后也执行校验,可以在 setValue 后手动执行 validate

formApi.setValue(field,  value);
formApi.validate([field]);

或者你已经赋了一个合法的值的情况下,希望清空旧的 value 的校验状态, 直接调用 formApi.setError(field, '')清空也可以。

HaceraI commented 1 year ago

好的,已经理解了这个❤

setValue 的作用仅在于 手动对 Field 赋值,手动赋值的情况下并不会触发 onChange事件,校验是与 onChange、onBlur之类的回调关联的,所以也并不会重新触发校验。 (对Form而言 ,Field都是受控组件。举Input 为例,对其setValue 等同于 更新 props.value,手动赋值时由于用户已经知道值是什么,是不应该触发 onChange的)