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

ReactJS表单组件的最佳实践

万浩淼
2023-03-14

我正在寻找一个最佳实践,有一个ReactJS组件负责用户编辑给定实体的表单。非常简单的例子。在许多情况下,实际的表单会有更多的字段和更多的GUI功能

React.createClass({
    getInitialState: function() {
        return {
            entity: {
                property1: null,
                property2: null
            }
        };
    },

    handleChange: function(e) {
        var entity = this.state.entity;

        switch(e.target.name) {
            case 'property1':
                entity.property1 = e.target.value;
                break;
            case 'property2':
                entity.property2 = e.target.value;
                break;
        }

        this.setState({
            entity: entity
        });
    },

    render: function() {
        return (
            <div className="entity-form">
                <form onChange={this.handleChange}>
                    <input type="text" name="property1" value={this.state.entity.property1} />
                    <br />

                    <textarea name="property2" value={this.state.entity.property2}></textarea>
                    <br />
                </form>
            </div>
        );
    }
});

表单的字段直接编辑实体对象,然后将其保存到RESTful API中。我希望组件被更新,因为用户改变字段,所以GUI可以根据输入在键入(如验证,信息等)。

    null

在上面的简化示例中,我使用受控输入。这导致在每次更改时更新状态并重新呈现组件(就像文本字段中输入的每个字符一样)。这是最好的做法吗?好的一点是,组件可以完全控制发生的事情,而不是使用defaultValue paramters,并且在某些事件(如用户按下save按钮)时,组件提取值,更新实体并将其保存到服务器。在这种情况下,是否应该使用受控或不受控输入,有任何理由(或意见)?

该示例在form标记上有一个onChange,它会导致每次更改窗体中的任何字段时调用handleChange方法。但是,由于输入是受控制的(有值参数),React抱怨输入字段没有onChange属性。这是否意味着在表单标记上使用一个公共onChange是不好的做法,我应该删除它并在每个字段上放置onChange?

在上面的示例中,我根据正在更新的输入字段使用了一个开关(当调用handleChange时)。我想我可以确保所有字段名与实体的属性名同步,并且可以根据事件中的字段名(e.target.name)在handleChange中设置实体对象的属性。然而,这使得每个字段很难有单独的需求,即使大多数字段只是直接更新实体属性。我想alternativ是一个开关,它根据输入的名称设置缺省块,并为任何需要其他更新方式的字段设置大小写块(比如在实体上设置值之前过滤值)。如果你知道更好的处理字段更新的方法,请对此发表评论。

共有1个答案

和斌
2023-03-14
  1. 任何要更改的内容都处于状态。
  2. 如果您想要加载一个现有实体并对其进行编辑,那么您需要受控的输入,并且需要相应地设置值。在大多数情况下,我倾向于远离defaultValue(下拉列表之外)
  3. 这与你前面的问题有关。如果指定值,则使用的是受控输入,并且必须为任何受控输入提供onChange处理程序,否则它将是固定不变的。受控输入的一个好处是用户不能编辑它们,所以如果您锁定了一些属性(可能是出于只读和安全原因),当用户试图保存时,即使他们直接编辑了HTML,React也应该从vDOM表示中提取属性的值(这里可能是错误的,但我相信我以前已经测试过了)。无论如何,您必须在受控输入上直接设置onChange。就使用事件delgation(在表单级别)而言,对于许多事件来说,这并不是一个糟糕的做法,这只是一个特定的场景(受控输入),在这个场景中,您需要为每个元素指定onChange事件。
  4. 不完全确定这个问题的要求是什么,但我使用了refs而不是target.name.
  5. 所以,您是正确的,永远不要直接更改状态,这是文档中的一个棘手之处。React将直接改变状态,它只是通过SetState在实现中完成。如果在此方法调用之外更改状态,将发生意外情况并引发错误。

shouldComponentUpdate只做粗浅的比较,但是这里有一些解决方案。

一个是字符串对象,这是一个快速和肮脏的对象比较,不是真的推荐它,但它是有效的。

我在React+Flux中使用的一个更好的解决方案是实现一个propertyChanged bool,只需在您的ShouldComponentUpdate中检查一下即可。

现在,这将要求您意识到当事情发生变化时设置它,即您在对象图中更深层次地改变了一些东西。假设propertyOne是一个对象,其属性在handleChange方法中被更改。您可以任意验证输入,然后设置propertyChanged=true,然后需要实现ComponentDidUpDate。我们在这里做了一个假设,但是如果组件已经更新,则将propertyChanged设置为false,这样就不会再触发不必要的更新了。我希望这有道理。这有点像单向通知属性改变。

我提供了一个快速的示例,说明我可能会为一个更动态的实现做些什么,该实现允许您向对象添加更多的属性(在这个实现中,只有浅层属性,显然您可以编写一个更健壮的解决方案)。如果你有任何进一步的问题或如果我没有回答什么,请告诉我。

http://jsfiddle.net/rpv9trhh/

var e = {
    prop1: 'test',
    prop2: 'wee',
    prop3: 'another property',
    propFour: 'Oh yeah!'
};

var FormComp = React.createClass({
    getInitialState: function(){
        return {
            entity: this.props.entity
        }
    },
    render: function() {

        var ent = this.state.entity;
        var that = this;
        var inputs = [];

        for(var key in ent){
            inputs.push(<input 
               key={key} 
               style={{display:'block'}} 
               type="text" 
               ref={key} onChange={that._propertyChanged.bind(null, key)}
               value={ent[key]} />)
        }

        return <form>
            {inputs}
            <input 
                type="button" 
                onClick={this._saveChanges} 
                value="Save Changes" />
        </form>;
    },
    _propertyChanged: function(propName) {
        var nextProp = this.refs[propName].getDOMNode().value;
        var nextEntity = this.state.entity;
        nextEntity[propName] = nextProp;

        this.setState({
            entity: nextEntity
        });
    },
    _saveChanges: function() {
        var updatedEntity = this.state.entity;

        for(var key in updatedEntity){
            alert(updatedEntity[key]);
        }

        //TODO: Call to service to save the entity, i.e.    
        ActionCreators.saveEntity(updatedEntity);
    }
});

React.renderComponent(<FormComp entity={e} />, document.body);
 类似资料:
  • 问题内容: 我在Java线程方面有一些经验,但我想知道… 存储多个线程的最佳实践是什么,我可以在其中单独或成组访问这些线程? 我自己的解决方案是创建一个类,但是自然地,我希望使用更可靠的本机类。 提前致谢! 编辑 显然,功能对于最佳方法非常重要。好吧,我举一个例子: 我有一个基本上可以同时搜索大量信息的应用程序,因此我正在使用线程。但是,每个线程仅需要执行整个操作的一部分,因此我希望添加其他参数来

  • 本文向大家介绍基于AngularJS前端云组件最佳实践,包括了基于AngularJS前端云组件最佳实践的使用技巧和注意事项,需要的朋友参考一下 AngularJS是google设计和开发的一套前端开发框架,他能帮助开发人员更便捷地进行前端开发。AngularJS是为了克服HTML在构建应用上的不足而设计的,它非常全面且简单易学习,因此AngularJS快速的成为了javascript的主流框架。

  • 引子 Rax 提供的长列表标签有很多,在什么场景下使用什么列表组件,怎样选择列表组件性能会更好,这些问题可能会给刚接触 Rax 的同学带来困扰。本文结合 Rax 0.5 发布版本对列表能力进行一次详细的梳理。 如何让页面滚动 在开始正题之前先说说为什么要有长列表的概念,以及如何让页面可以滚动。 传统的 Web 页面天生在浏览器里就是可以滚动的,我们额外引入一个滚动容器的概念好像比较多余。但当我们做

  • 问题内容: 我正在根据其在视口中的位置为几个React.js组件设置动画。如果组件中视,动画不透明度为1,如果不是在视口中,有生其不透明度为0。我使用的和属性,以确定该组件是视域之内。 ComponentA显示了我遵循的其他B,C和D组件的模式。他们每个人都在监听滚动事件。 这是每个组件都必须向事件添加事件侦听器的“反应”方式吗?同一窗口上有多个滚动事件侦听器? 还是通过在所有者组件处将滚动事件侦

  • 这里有些给使用和编写 Ansible playbook 的贴士. 你能在我们的 ansible-example repository.找到展示这些最佳实践的 playbook 样例.(注意: 这些示例用的也许不是最新版的中所有特性,但它们仍旧是极佳的参考.) Topics 最佳实践 接下来的章节将向你展示一种组织 playbook 内容方式. 你对 Ansible 的使用应该符合你的需求而不是我们

  • 处理后台任务与常规调用方法有很大的不同。本指南旨在帮助让您的后台任务平稳有效地运行。本文基于 这篇博客文章。 使任务参数小而简单 方法(任务)在调用之前会被序列化。使用 TypeConverter 类将参数转换为 JSON 字符串。如果您有复杂的实体和 / 或大对象; 包括数组,最好将它们放入数据库,然后只将其标识 (id) 传递给后台任务。 错误例子: public void Method(En