【问题标题】:React input tag disabled prop issue反应输入标签禁用道具问题
【发布时间】:2020-07-21 03:21:58
【问题描述】:

我正在尝试在 React.js 中构建一个登录表单。我想根据验证方法返回的结果启用/禁用登录按钮。 React 抛出错误“标签上的 prop disabled 的值无效。要么将其从元素中移除,要么传递一个字符串或数值以将其保留在 DOM 中。'。有没有人遇到过同样的错误?帮助我了解这里出了什么问题?

import React, { Component } from "react";
import Input from "../common/input";
import Joi from "joi-browser";

class LoginForm extends Component {
  state = {
    account: {
      username: "",
      password: "",
    },
    errors: {},
  };

  schema = {
    username: Joi.string().required().label("Username"),
    password: Joi.string().required().label("Password"),
  };

  abortEarly = {
    abortEarly: false,
  };

  handleSubmit = (event) => {
    event.preventDefault();
    const errors = this.validate();
    if (errors) return;
    console.log("submitted");
  };

  validate = () => {
    const result = Joi.validate(
      this.state.account,
      this.schema,
      this.abortEarly
    );
    const errors = {};
    if (!result.error) return null;
    result.error.details.map((detail) => {
      errors[detail.path[0]] = detail.message;
      return detail.path[0];
    });
    // console.log(errors);
    this.setState({ errors });
    return errors;
  };

  validateProperty = ({ name, value }) => {
    const propertyTobeValidated = { [name]: value };
    const schema = { [name]: this.schema[name] };
    const { error } = Joi.validate(propertyTobeValidated, schema);
    return error ? error.details[0].message : null;
  };

  handleChange = ({ currentTarget }) => {
    const errors = { ...this.state.errors };
    const error = this.validateProperty(currentTarget);
    if (error) errors[currentTarget.name] = error;
    else delete errors[currentTarget.name];
    const account = { ...this.state.account };
    account[currentTarget.name] = currentTarget.value;
    this.setState({ account, errors });
  };

  render() {
    const { account, errors } = this.state;
    return (
      <div>
        <h1>Login</h1>
        <form onSubmit={this.handleSubmit}>
          <Input
            label="Username"
            name="username"
            value={account.username}
            onChange={this.handleChange}
            error={errors.username}
          ></Input>
          <Input
            label="Password"
            name="password"
            value={account.password}
            onChange={this.handleChange}
            error={errors.password}
          ></Input>

          <button disabled={this.validate} className="btn btn-primary">
            Login
          </button>
        </form>
      </div>
    );
  }
}

export default LoginForm;

【问题讨论】:

  • disabled 是布尔属性而不是函数。你的 this.validate 是一个函数

标签: reactjs disabled-input


【解决方案1】:

Disabled 是一个布尔属性,意味着它的值只能是 true 或 false。您的验证函数不是布尔值,而是返回一个对象,因此 React 会抛出“无效值”错误。为了解决这个问题,您可以检查this.validate 的结果是否为空:

<button 
    disabled={(this.validate() !== null)} 
    className="btn btn-primary"
>
    Login
</button>

另外,你忘记给你的this.validate打电话了:)

关于“最大更新深度...”,您应该从this.validate 中删除this.setState,因为您已经在handleChange 方法中将错误置于状态。

【讨论】:

  • 我尝试了您的解决方案。我现在面临错误:“超出最大更新深度。当组件在 componentWillUpdate 或 componentDidUpdate 中重复调用 setState 时,可能会发生这种情况。React 限制了嵌套更新的数量以防止无限循环。”我正在使用 React 16.9 版。关于您的建议,在反应中,我们会在任何操作上传递方法的参考;因此我把 disabled={this.validate}.
  • 在这种情况下,您不应该传递对方法的引用,而是传递它返回的值,因为 button 需要 disabled 属性中的值
  • 我修改了答案,现在它应该有助于最大更新深度
  • 感谢您的帮助。有效。我有一个错误的概念,在对标签的每个道具做出反应时,我们需要传递方法的引用。
【解决方案2】:

给你一个解决方案

import React, { Component } from "react";
import Input from "../common/input";
import Joi from "joi-browser";

class LoginForm extends Component {
  state = {
    account: {
      username: "",
      password: "",
    },
    errors: {},
  };

  schema = {
    username: Joi.string().required().label("Username"),
    password: Joi.string().required().label("Password"),
  };

  abortEarly = {
    abortEarly: false,
  };

  handleSubmit = (event) => {
    event.preventDefault();
    const errors = this.validate();
    if (errors) return;
    console.log("submitted");
  };

  validate = () => {
    const result = Joi.validate(
      this.state.account,
      this.schema,
      this.abortEarly
    );
    const errors = {};
    if (!result.error) return false;
    result.error.details.map((detail) => {
      errors[detail.path[0]] = detail.message;
      return detail.path[0];
    });
    // console.log(errors);
    this.setState({ errors });
    return true;
  };

  validateProperty = ({ name, value }) => {
    const propertyTobeValidated = { [name]: value };
    const schema = { [name]: this.schema[name] };
    const { error } = Joi.validate(propertyTobeValidated, schema);
    return error ? error.details[0].message : null;
  };

  handleChange = ({ currentTarget }) => {
    const errors = { ...this.state.errors };
    const error = this.validateProperty(currentTarget);
    if (error) errors[currentTarget.name] = error;
    else delete errors[currentTarget.name];
    const account = { ...this.state.account };
    account[currentTarget.name] = currentTarget.value;
    this.setState({ account, errors });
  };

  render() {
    const { account, errors } = this.state;
    return (
      <div>
        <h1>Login</h1>
        <form onSubmit={this.handleSubmit}>
          <Input
            label="Username"
            name="username"
            value={account.username}
            onChange={this.handleChange}
            error={errors.username}
          ></Input>
          <Input
            label="Password"
            name="password"
            value={account.password}
            onChange={this.handleChange}
            error={errors.password}
          ></Input>

          <button disabled={this.validate} className="btn btn-primary">
            Login
          </button>
        </form>
      </div>
    );
  }
}

export default LoginForm;

validate 方法应返回布尔值(真或假)

【讨论】:

  • 这是一个很好的解决方案,但我认为如果渲染完全由状态决定,它更易于维护。除了作为错误对象的状态之外,我要么添加另一条指示存在错误的状态,要么将 errors 状态转换为包含 length 属性的数组,所以&lt;button disabled={this.errors.length}
  • @Shiladitya 我尝试了您建议的解决方案。我仍然面临同样的错误。登录按钮默认启用。我正在使用 React 16.9。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-18
  • 2018-09-17
  • 2022-10-14
  • 2014-11-21
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
相关资源
最近更新 更多