当前位置: 首页 > 知识库问答 >
问题:

超文本标记语言表单应该是受控的还是不受控制的组件?

丌官翰采
2023-03-14

对于我的国家应该住在哪里,我有一个两难的选择。

React Docs提到:

识别基于该状态呈现某些内容的每个组件。查找公共所有者组件(层次结构中需要状态的所有组件之上的单个组件)。公共所有者或层次结构中更高级别的另一个组件应该拥有该状态。如果您找不到一个拥有状态的组件,只需创建一个新组件来保存状态,并将其添加到公共所有者组件之上的层次结构中。

我有一个简单的注释UI。

  1. 用户在文本区域中输入注释

组件Highrarch如下:

 - CommentSection.jsx ---> main (should "Post" state (?))
   -comment-post.jsx  ---> User Comment Form
   - comment-table.jsx
     - comment.jsx 
       - comment-avatar.jsx 
       - comment-body.jsx 

问题:在评论文章中。jsxinput和textarea字段有onChange()事件处理程序,在submit post按钮上还有一个click事件处理程序。我可以选择执行以下两种操作之一:

  1. 评论文章中。jsx当触发onChange时,将commentBody发送到CommentSection。jsx这里的问题是,我将在用户输入后尽快发送commentBody,然后在触发时发送name,依此类推
  2. 评论文章中。jsx当onChange被触发时,在状态中保存值,然后在状态中命名名称字段,当用户单击提交按钮发送到CommentSection时。jsxBenefit is字段首先在状态中设置,当用户单击post时,它们会被发送到父级(应该是这样吧?)

注释的输入字段,即注释正文和名称是否应保存在注释帖子中。jsx(表单组件)还是父级?

现在我正在做的是2。在状态中保存表单字段,然后在提交时发送状态值。

我认为问题在于onChange和onClick是两个不同的处理程序,问题是哪一个应该理想地将值传递给父组件?

    class CommentSection extends Component {
      state = {
        posts: []
      };

      handleCommentPost = post => {
        const posts = this.state.posts;

        posts.push(post);
        this.setState({ posts });
      };

      render() {
        console.log("comment:", this.state.posts);

        return (
          <React.Fragment>
            <h1>comments</h1>
            <div className="row bootstrap snippets">
              <div className="col-md-6 col-md-offset-2 col-sm-12">
                <div className="comment-wrapper">
                  <Comment_Post onClick={this.handleCommentPost} />
                  <Comment_Table comments={this.state.posts} />
                </div>
              </div>
            </div>
          </React.Fragment>
        );
      }
    }

    class Comment_Table extends Component {
       render() {
        const posts = this.props.comments;
        let count = 0;

        return (
          <div className="panel panel-info">
            <hr />
            <ul className="media-list">
              {posts.map(post => (
                <Comment key={count++} comment={post.commentBody} />
              ))}
            </ul>
          </div>
        );
      }
    }



class Comment extends Component {
  render() {
    return (
      <li className="media">
        <Comment_Avatar userAvatar={this.props.commentAvatar} />
        <Comment_Body userComment={this.props.comment} />
      </li>
    );
  }
}

class Comment_Body extends Component {
  render() {
    const { userComment } = this.props;
    return (
      <div className="media-body">
        <span className="text-muted pull-right">
          <small className="text-muted">30 min ago</small>
        </span>
        <strong className="text-success">@MartinoMont</strong>
        <p>
          {userComment}
          {}
        </p>
      </div>
    );
  }
}
class Comment_Post extends Component {
  state = {
    commentBody: null
  };
  onCommentChange = e => {
    this.setState({ commentBody: e.target.value });
  };

  onCommentPost = e => {
    const commentBody = this.state.commentBody;
    if (commentBody !== null) {
      this.props.onClick({ commentBody });
    }
  };
  onNameInput = e => {};

  onCommentPostError() {}

  render() {
    return (
      <React.Fragment>
        <div className="panel-heading p-heading">Comment panel</div>
        <div className="panel-body">
          <textarea
            onChange={this.onCommentChange}
            className="form-control"
            placeholder="write a comment..."
            rows="3"
          />
          <label htmlFor="fname" onChange={this.onNameInput}>
            Name:{" "}
          </label>
          <input id="fname" placeholder="John" />
          <br />
          <button
            type="button"
            className="btn btn-info pull-right"
            onClick={this.onCommentPost}
          >
            Post
          </button>
          <div className="clearfix" />
        </div>
      </React.Fragment>
    );
  }
}

class Comment_Avatar extends Component {
  render() {
    return (
      <a href="#" className="pull-left">
        <img
          src="https://bootdey.com/img/Content/user_1.jpg"
          alt=""
          className="img-circle"
        />
      </a>
    );
  }
}

共有1个答案

茅鸿宝
2023-03-14

我认为问题在于onChange和onClick是两个不同的处理程序,问题是哪一个应该理想地将值传递给父组件?

我们在标准用户界面设计中使用两种类型的表单。首先是当输入中的任何更改保存更改时。其次,在对表单元素进行更改后,按“提交”按钮,然后保存更改。

由于您已经实现了第二种类型,您的onChange应该处理控制您的TextArea状态,而onClick应该处理提交。所以你的代码很好。

对于我的国家应该住在哪里,我有一个两难的选择。

那要看。。。在本例中,您只有一个表单和两个表单元素,它们都不可重用。所以这些不受控制的形式对你很有效。但是,如果您想要一个可重用的表单组件,或者想要一个包含15个字段的表单,那么您不需要为每个字段编写单独的onChange处理程序。为此,您需要制作一个受控表单组件,它可以为您处理所有这些事情。下面是一个这样的例子。

export default class Form extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      values: {}
    };
  }

  @boundMethod
  handleSubmit(event) {
    event.preventDefault();

    this.props.submit(this.state.values);
  }

  @boundMethod
  handleChange(event) {
    const { name, value } = event.target;
    const newValues = Object.assign(
      { ...this.state.values },
      { [name]: value }
    );
    this.setState({
      values: newValues
    });
  }

  public render() {
    const { values } = this.state;
    return (
      <form onSubmit={this.handleSubmit} noValidate={true}>
        <div>
          {React.Children.map(
            this.props.children,
            child => (
                {React.cloneElement(child, {
                  value: values[child.props.name],
                  onChange: this.handleChange
                })}
            )
          )}
          <div>
            <button type="submit">
              Submit
            </button>
          </div>
        </div>
      </form>
    );
  }
}

然后,您将能够像这样使用这个Form类:

<Form
  submit={values => {
    /* work with values */
  }}
>
  <input type="hidden" name="name" />
  <input type="hidden" name="rating" />
</Form>;
 类似资料:
  • 问题内容: ReactJS中什么是受控组件和非受控组件?它们之间有何不同? 问题答案: 这与有状态DOM组件(表单元素)有关,而React文档解释了区别: 甲控制的部件是一个,通过取其电流值和通过像回调通知变化。父组件通过处理回调并管理其自身的状态并将新值作为道具传递给受控组件来“控制”它。您也可以将其称为“哑组件”。 一个不受控制的组件是一个存储其自己的内部状态,并且您使用查询DOM ,当你需要

  • 我正在使用ITextRenderer从html生成PDF。然而,我得到以下异常: 你能帮帮我吗? 任何帮助都将不胜感激。 先谢谢你。

  • 问题内容: 几乎在每个ReactJS教程中,甚至在用于处理输入更改的官方文档中,都建议使用onChange。我们使用状态作为值,并通过onChange对其进行更改。这会在每个按键中触发渲染。所以, 渲染真的那么便宜吗? 输入值不保存在DOM中吗?因此DOM和VirtualDOM之间没有区别,因此尽管渲染发生了什么变化?(可能是错误的假设)。 出于娱乐和学习目的,我尝试了以下方法: 使用自定义函数和

  • 在大多数情况下,我们推荐使用受控组件来实现表单。在受控组件中,表单数据由React组件处理。另外一个可选项是不受控组件,其表单数据由DOM元素本身处理。 不同于对每次状态处理都需要编写事件处理函数程序,在不受控组件中,你可以使用ref从DOM获得表单数据。 例如,在不受控组件中,以下代码可以输入名字: class NameForm extends React.Component { const

  • 问题内容: 警告:组件正在更改要控制的文本类型的不受控制的输入。输入元素不应从不受控制切换为受控制(反之亦然)。确定在组件的使用寿命中使用受控或非受控输入元素。* 以下是我的代码: 问题答案: 原因是,在您定义的状态下: 字段作为空白对象,因此在第一次渲染期间将是,输入字段的值将为: 因此,输入字段将变得不受控制。 在输入中输入任何值后,状态将变为: 那时输入字段被转换为受控组件;这就是为什么您得