next
next copied to clipboard
[Field]自定义组件在unmount后,还是校验了
Component
Field
Reproduction link
https://riddle.alibaba-inc.com/riddles/27d1ebab
import ReactDOM from 'react-dom';
import React from 'react';
import { Input, Button, Checkbox, Field,Form,Select } from '@alifd/next';
const CheckboxGroup = Checkbox.Group;
const dataSource=[1,2,3];
const MySelect = (props) => {
return <Select {...props}/>
}
class App extends React.Component {
field = new Field(this, {scrollToFirstError: -10});
notEmpty(rule, value) {
if (!value || value.length==0) {
return Promise.reject("必选");
} else {
return Promise.resolve(null);
}
}
render() {
const init = this.field.init;
return (<div className="demo">
<Form field={this.field}>
<Form.Item>
<Input
{...init('input', {
})} />
</Form.Item>
{
this.field.getValue('input') &&
<>
<Form.Item>
<Select
multiple
dataSource={dataSource}
{...init('next_select', {
rules: [{validator: this.notEmpty}]
})} />
</Form.Item>
<Form.Item>
<MySelect
multiple
dataSource={dataSource}
{...init('my_select', {
rules: [{validator: this.notEmpty}]
})} />
</Form.Item>
</>
}
</Form>
<br/>
<Button type="primary" onClick={() => {
this.field.validatePromise().then(({errors, values}) => {
console.warn('aaa errors',errors);
console.log('aaa values',values)
});
}}>validate</Button>
</div>);
}
}
ReactDOM.render(<App/>, mountNode);
Steps to reproduce
-
Input输入1,点Validate按钮,next_select、my_select为空,校验不通过 => 符合预期

-
Input清除,点Validate按钮,next_select、my_select都被Unmount了,不应该校验。 next_select => 没有校验,符合预期 my_select => 校验了,不符合预期

next_select是fusion原生组件,my_select只是包装成自定义组件(但里面也是Fusion原生组件)
const MySelect = (props) => {
return <Select {...props}/>
}
你的组件不支持 ref,需要用 React.forwordRef 包裹下
const MySelect = React.forwordRef((props, ref) => {
return <Select {...props} ref={ref}/>
})
那最好在文档描述一下这个问题和解法。
但我觉得这样对使用上很不方便,你们再看看,能否改变实现,不要靠ref
那最好在文档描述一下这个问题和解法。
但我觉得这样对使用上很不方便,你们再看看,能否改变实现,不要靠ref
- 文档我加下。
- 如果你不写ref,我就得包裹一层组件,比较担心性能的问题
包裹一层组件,比较担心性能的问题 =>
能否在useField的参数,让用户选择是否要包组件,默认可以不开启。 我想大部分场景都不太会有性能问题,使用上会方便很多(不然每次用这个组件,都需要传个ref)
可以业务线自己写 HOC 包裹下组件,不一定要传 Ref,只需要用 HOC 里面用 React.Component 包裹下。
Fusion 的基础组件都是 React.Component ,所以不需要包裹。
1. 直接用 React.Component 包裹
包裹方式:
import OldComponent from './xxxx';
export default class NewComponent extends React.Compoent {
render() {
return <OldComponent {...this.props} />
}
}
HOC 方式:
export default function HOC(Component) {
class NewComponent extends React.Compoent {
render() {
return <Component {...this.props} />
}
}
return NewComponent;
}
2. 使用 React.forwordRef 包裹函数式组件
const XXX = React.forwordRef((props, ref) => {
// ref 必须触达真实 Element
return <span ref={ref}>.....</span>
});
FormItem为什么依赖ref回调的执行来监听组件的挂载和卸载呢,个人觉得通过高阶组件包裹子组件,然后高阶组件didMount和unMount中监听卸载和挂载会好一些?或者这种方式是有什么问题吗?
`class Wrap extends React.Component { componentDidMount(): void { console.log('挂在') }
componentWillUnmount(): void { console.log('卸载') } render() { return <>{this.props.children}</> } }
function FormItem (props) { const s = React.Children.map(props.children, (c, i) => { return 《Wrap》{c}《/Wrap》 }) return ( <>{s}</> ) }`
因长期不活跃关闭,如需继续跟进请重提 issue