react-component / form

React High Order Form Component(web & react-native)
http://react-component.github.io/form/
MIT License
1.81k stars 296 forks source link

rc-form特殊场景下报错Cannot read property 'filter' of undefined #513

Open lyz810 opened 3 years ago

lyz810 commented 3 years ago

rc-form版本:2.4.12

部分错误堆栈信息:

Uncaught TypeError: Cannot read property 'filter' of undefined
    at Object.getRules (createBaseForm.js:263)
    at createBaseForm.js:403
    at Array.forEach (<anonymous>)
    at Object.validateFieldsInternal (createBaseForm.js:390)
    at Object.onCollectValidate (createBaseForm.js:143)
    at MyComponent.componentDidMount (demo.jsx:8)

应用场景: 自定义组件MyComponent在ComponentDidMount时会检测一下props的值是否符合规范(百分数需转为小数),并通过onChange抛给form,以便通过validate检测 实际场景中MyComponent实现较复杂,在hidden状态下不希望渲染MyComponent,所以如果隐藏该问题则渲染一个空div不渲染MyComponent,点击按钮后再渲染 此时会报错(该字段设置了校验规则) 目前通过了一些手段绕过了此问题,但对性能有一定影响,希望组件能处理下这种场景下的报错

可重现最简Demo:

// demo.jsx
import React from 'react';
import { createForm } from 'rc-form';

class MyComponent extends React.PureComponent {
    componentDidMount() {
        const { value, onChange } = this.props;
        if (value && value.endsWith('%')) {
            onChange(value.replace('%', '') / 100);
        }
    }

    render() {
        return this.props.value;
    }
}

@createForm()
class Form extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            hidden: true,
        };
    }

    render() {
        const { form } = this.props;
        const { hidden } = this.state;
        return (
            <>
            <button onClick={() => this.setState({
                hidden: false,
            })}>click me</button>
            <div>
                {form.getFieldDecorator('id', {
                    initialValue: '50%',
                    hidden,
                    rules: [{
                        pattern: /^[\d.]+$/,
                        message: 'xx',
                    }],
                })(hidden ? <div hidden /> : <MyComponent />)}
            </div>
            </>
        );
    }
}

export default Form;

重现步骤: 点击按钮,直接报错