提交 React 表单后如何清除 Bootstrap 4 个错误?

How do I clear Bootstrap 4 errors after I submit my React form?

我将 React 16.13.0 与 Bootstrap 4 一起使用。我创建了以下组件,我在我的 React 表单中使用了...

const Input = (props) => {
    return (  
  <div className="form-group">
      <FormLabel>{props.title}</FormLabel>
      <FormControl
            isInvalid={props.errors && Boolean(props.errors[props.name])}
            type={props.type}
            id={props.name}
            name={props.name}
            value={props.value}
            placeholder={props.placeholder}
            onChange={props.handleChange}
          />

      {props.errors && props.errors[props.name] && (
          <FormControl.Feedback type="invalid">
                 {props.errors[props.name].map((error, index) => (
                     <div key={`field-error-${props.name}-${index}`} className="fieldError">{error}</div>
                 ))} 
          </FormControl.Feedback>
      )}
  </div>
    )
}

export default Input;

下面是处理表单提交功能以及我创建表单的一些容器...

  async handleFormSubmit(e) {
    e.preventDefault();
    const NC = this.state.newCoop;
    delete NC.address.country;

    try { 
      const response = await fetch(FormContainer.REACT_APP_PROXY + '/coops/',{
        method: "POST",
        body: JSON.stringify(this.state.newCoop),
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
      });

      if (response.ok) {
        const result = await response.json();
        window.flash('Record has been created successfully!', 'success') 
        return result;
      }
      throw await response.json();
    } catch (errors) {
      console.log('_error_: ', errors);
      this.setState({ errors });
    }  
  }

...

  render() {
    if (this.state.coopTypes && !this.state.coopTypes.length) {
      return null;
    }
    return (
      <div>
        <form className="container-fluid" onSubmit={this.handleFormSubmit}>
            <FormGroup
                controlId="formBasicText">      

                <Input inputType={'text'}
                   title= {'Name'} 
                   name= {'name'}
                   value={this.state.newCoop.name} 
                   placeholder = {'Enter cooperative name'}
                   handleChange = {this.handleInput}
                   errors = {this.state.errors} 
                   /> {/* Name of the cooperative */}

问题是,在我提交表单后,如果之前 运行 出现错误,它们仍会显示在屏幕上。

在成功提交表单后,是否有清除 Bootstrap 错误显示的标准方法?

由于您正在使用 this.state.errors<Input> 组件提供错误信息 prop,您只需更新 handleInput(...) 函数以在您的 this.state.errors 时清除 this.state.errors输入值变化。这个想法是这样的:

handleInput = (event) => {
  const errors = Object.assign({}, this.state.errors);
  const target = event.target;

  // remove the error value for a specific input only
  delete errors[target.name];
  this.setState({ errors });

  // Do whatever else needs to be done here for your input
}

这是一个工作示例:https://jsfiddle.net/4gqr0cfa/

您需要根据表单是否有效来添加或删除表单验证。为此,请在最初设置为 false 的 Form 上添加 validated 属性。

我怎样才能让它发挥作用?

按照以下步骤操作:

  1. 在包含 Form 的组件中创建一个布尔状态变量,其初始值应为 false。

    const [validated, setValidated] = useState(false);
    
  2. 在表单上添加一个名为 validated 的属性,并将其值设置为等于在步骤 1 中创建的布尔状态变量。

    <Form validated={validated}>
       ...
    </Form>
    
  3. 提交表单时,检查表单是否有效,如果有效,则将状态变量validated设置为true

这是一个工作演示

function App() {
  const [ validated, setValidated ] = React.useState(false);
  const [ form, setForm ] = React.useState({
    fields: {
      name: { type: 'text', value: '', title: 'Name' },
      email: { type: 'email', value: '', title: 'Email' },
      password: { type: 'password', value: '', title: 'Password' }
    },
    errors: {}
  });

  const handleSubmit = (event) => {
    event.preventDefault();
    const errors = {};
    let invalid = false;

    Object.entries(form.fields).forEach(([k, v]) => {
      if (!errors[k]) errors[k] = [];
      
      if (!v.value) {
        errors[k].push(`${k} is required`);
        invalid = true;
      }

      if (k === 'email' && !v.value.includes('@')) {
        errors[k].push('enter a valid email address');
        invalid = true;
      }

      if (k === 'password' && v.value.length < 8) {
        errors[k].push('password should be atleast 8 characters long');
        invalid = true;
      }
    });

    setForm({ ...form, errors });

    if (invalid) {
      setValidated(false);
    } else {
      setValidated(true); 
    }
  };

  const handleChange = ({ target }) => {
    const updatedField = { ...form.fields[target.name], value: target.value };
    
    const fields = { 
      ...form.fields,
      [target.name]: updatedField
    };

    setForm({ ...form, fields });
  };

  return (
    <div style={{ maxWidth: '300px', margin: '10px auto'}}>
      <ReactBootstrap.Form noValidate validated={validated} onSubmit={handleSubmit}>
        {
          Object.entries(form.fields).map(([k, v]) => {
            return (
              <Input
                key={k}
                title={v.title}
                type={v.type}
                name={k}
                value={v.value}
                placeholder={v.title}
                handleChange={handleChange}
                errors={form.errors}
              />
            );
          })
        }
        <ReactBootstrap.Button type="submit">Submit form</ReactBootstrap.Button>
      </ReactBootstrap.Form>
    </div>
  );
}



const Input = (props) => {
    return (  
      <ReactBootstrap.Form.Group>
        <ReactBootstrap.FormLabel>{props.title}</ReactBootstrap.FormLabel>
        <ReactBootstrap.FormControl
          isInvalid={
            Array.isArray(props.errors[props.name])
             ? props.errors[props.name].length > 0
                 ? true : false
             : false
          }
          type={props.type}
          id={props.name}
          name={props.name}
          value={props.value}
          placeholder={props.placeholder}
          onChange={props.handleChange}
        />

        {props.errors && props.errors[props.name] && (
            <ReactBootstrap.FormControl.Feedback type="invalid">
                  {props.errors[props.name].map((error, index) => (
                      <div key={`field-error-${props.name}-${index}`} className="fieldError">{error}</div>
                  ))} 
            </ReactBootstrap.FormControl.Feedback>
        )}
      </ReactBootstrap.Form.Group>
    )
}


ReactDOM.render(<App />, document.getElementById('root'));
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/1.1.0-rc.0/react-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.min.js"></script>

<div id="root"></div>

您也可以在 stackblitz

上观看相同的演示

您可以改进上述演示,通过使用 is-validis-invalid 类 分别添加绿色或红色边框来向用户指示输入字段有效或无效。

function App() {
  const [ validated, setValidated ] = React.useState(false);
  const [ form, setForm ] = React.useState({
    fields: {
      name: { type: 'text', value: '', title: 'Name' },
      email: { type: 'email', value: '', title: 'Email' },
      password: { type: 'password', value: '', title: 'Password' }
    },
    errors: {}
  });

  const handleSubmit = (event) => {
    event.preventDefault();
    const errors = {};
    let invalid = false;

    Object.entries(form.fields).forEach(([k, v]) => {
      if (!errors[k]) errors[k] = [];
      
      if (!v.value) {
        errors[k].push(`${k} is required`);
        invalid = true;
      }

      if (k === 'email' && !v.value.includes('@')) {
        errors[k].push('enter a valid email address');
        invalid = true;
      }

      if (k === 'password' && v.value.length < 8) {
        errors[k].push('password should be atleast 8 characters long');
        invalid = true;
      }
    });

    setForm({ ...form, errors });

    if (invalid) {
      setValidated(false);
    } else {
      setValidated(true); 
    }
  };

  const handleChange = ({ target }) => {
    const updatedField = { ...form.fields[target.name], value: target.value };
    
    const fields = { 
      ...form.fields,
      [target.name]: updatedField
    };

    setForm({ ...form, fields });
  };

  return (
    <div style={{ maxWidth: '300px', margin: '10px auto'}}>
      <ReactBootstrap.Form noValidate validated={validated} onSubmit={handleSubmit}>
        {
          Object.entries(form.fields).map(([k, v]) => {
            return (
              <Input
                key={k}
                title={v.title}
                type={v.type}
                name={k}
                value={v.value}
                placeholder={v.title}
                handleChange={handleChange}
                errors={form.errors}
              />
            );
          })
        }
        <ReactBootstrap.Button type="submit">Submit form</ReactBootstrap.Button>
      </ReactBootstrap.Form>
    </div>
  );
}



const Input = (props) => {
    return (  
      <ReactBootstrap.Form.Group>
        <ReactBootstrap.FormLabel>{props.title}</ReactBootstrap.FormLabel>
        <ReactBootstrap.FormControl
          isInvalid={
            Array.isArray(props.errors[props.name])
             ? props.errors[props.name].length > 0
                 ? true : false
             : false
          }
          type={props.type}
          id={props.name}
          name={props.name}
          value={props.value}
          placeholder={props.placeholder}
          onChange={props.handleChange}
          className={
             Array.isArray(props.errors[props.name])
             ? props.errors[props.name].length > 0 ? 'is-invalid': 'is-valid'
             : ''
          }
        />

        {props.errors && props.errors[props.name] && (
            <ReactBootstrap.FormControl.Feedback type="invalid">
                  {props.errors[props.name].map((error, index) => (
                      <div key={`field-error-${props.name}-${index}`} className="fieldError">{error}</div>
                  ))} 
            </ReactBootstrap.FormControl.Feedback>
        )}
      </ReactBootstrap.Form.Group>
    )
}


ReactDOM.render(<App />, document.getElementById('root'));
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" />

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-bootstrap/1.1.0-rc.0/react-bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.0/js/bootstrap.min.js"></script>

<div id="root"></div>

stackblitz

上查看此演示

您可以在 react-bootstrap and bootstrap

的官方文档中阅读 bootstrap 中的表单验证