setState 在表单验证中没有按预期工作

setState not working as expected in the form validations

我对反应有点陌生,我正在尝试实现带有验证的动态表单。我从后端获取输入详细信息并根据它渲染组件。一切正常,但是当我尝试包括表单验证时(当用户提交表单时我想进行表单验证)它根本不起作用。我尝试了网络上的所有解决方案,但没有找到任何解决此问题的方法。谁能帮我解决这个问题?谢谢!!

这是我的代码

class Slider extends Component {
constructor(props) {
    super(props)
    const { providerConfigs } = this.props
    this.state = {
        hasError: false,
        inputs: [....]
    }
}

.....

handleOnSubmit = () => {
    this.setState({ hasError: false })

    const { providerMappingActions: { addProvider }, history } = this.props;
    const { inputs } = this.state;

    inputs.forEach(input => {
        if (input.isRequired && input.attributeValue.length === 0) {
            this.setState({ hasError: true })
        }
        if (input.attributeOptionId == 5 && input.attributeValue.length !== 0) {
            if (input.attributeValue.length !== 10) {
                this.setState({ hasError: true })
            }

        }
    })

    if (!this.state.hasError) {
        const attributes = inputs.map(input => {
            return {
                attributeName: input.attributeName,
                attributeValue: input.attributeValue,
                isRequired: input.isRequired,
                attributeOptionId: input.attributeOptionId,
            }
        });
        console.log(attributes)
        this.resetInputs();
    }
}

render() {
    const { hasError, inputs } = this.state;

    return (
        <div>
            <div >
                <div >
                   ....
                                                            </FormGroup>)
                                                            : (
                                                                <FormGroup key={input.attributeOptionId}>
                                                                    <FormControl
                                                                        name={input.attributeName}
                                                                        type={this.checkType(input.fieldType)}
                                                                        autoFocus={!input.value}
                                                                        value={input.value}
                                                                        onChange={(e) => { this.handleChange(e) }}
                                                                        className={`${(hasError && input.isRequired && input.attributeValue.length === 0) ? 'validation-field-error' :
                                                                            hasError && input.attributeOptionId === 5 && input.attributeValue != '' && input.attributeValue.length !== 10 ? 'validation-field-error' : ''}`}
                                                                    />
                                                                </FormGroup>)
                                                        }
                                                    </td>
                                                </tr>
                                            );
                                        })
                                    }
                                    <tr>
                                        <td colSpan={2} align='right'>
                                            {
                                                inputs.map(input => {
                                                    if (hasError && input.isRequired && input.attributeValue.length === 0) {
                                                        return <div
                                                            key={input.attributeOptionId}
                                                        >
                                                            <label className='validation-error-text'><b>{input.attributeName} is required!</b></label>
                                                        </div>
                                                    } else if (hasError && input.attributeOptionId == 5 && input.attributeValue != '' && input.attributeValue.length !== 10) {
                                                        return <div
                                                            key={input.attributeOptionId}
                                                        >
                                                            <label className='validation-error-text'><b>Insert valid {input.attributeName}!</b></label>
                                                        </div>
                                                    }
                                                }
                                                )
                                            }
                                        </td>
                                    </tr>
                                </tbody>
                            </table>
                            <FormGroup>
                                <div >
                                    <div style={{ paddingLeft: "20px", paddingRight: "20px" }}>
                                        <button
                                           
                                           ...
                                </div>
                            </FormGroup>
                        </form>
                    </div>
                </div>
            </div>

        </div >

    )
}}

请注意,我删除了一些代码以提高可读性。

setState() does not always immediately update the component. It may batch or defer the update until later. This makes reading this.state right after calling setState() a potential pitfall.

https://reactjs.org/docs/react-component.html#setstate

设置后立即读取状态并不能保证您期望的结果。重构为一个局部变量,只在函数结束时设置一次状态:

handleOnSubmit = () => {
    const hasError = false;
    const { providerMappingActions: { addProvider }, history } = this.props;
    const { inputs } = this.state;

    inputs.forEach(input => {
        if (input.isRequired && input.attributeValue.length === 0) {
            hasError = true;
        }
        if (input.attributeOptionId == 5 && input.attributeValue.length !== 0) {
            if (input.attributeValue.length !== 10) {
                hasError = true;
            }

        }
    })

    if (!hasError) {
        const attributes = inputs.map(input => {
            return {
                attributeName: input.attributeName,
                attributeValue: input.attributeValue,
                isRequired: input.isRequired,
                attributeOptionId: input.attributeOptionId,
            }
        });
        console.log(attributes)
        this.resetInputs();
    }

    // Set the state only once at the end of the function, this will
    // cause a re-render if the value changes.
    this.setState({ hasError });
}