【问题标题】:Render array of inputs in react在反应中渲染输入数组
【发布时间】:2016-03-23 03:02:41
【问题描述】:

我有一系列电子邮件(作为更大模型的一部分)。这些显示在单独的行中,每个行都有一个删除按钮(地址本身可以直接在输入框中更新)。不幸的是,当使用映射函数渲染输入时,我不知道如何做出反应。 (我正在将流星火焰项目转换为流星反应)。

一切都呈现,但我如何附加到更改事件,以便我可以更新我的电子邮件数组? onChange + value 需要以某种方式设置。

这是地图功能

return this.data.emailGroup.emails.map((email) => {
            return (
                <div key={email} className="input-group">
                    <input type="text" className="form-control" onChange={self.handleEmailListChange} value={email}/>

                    <div className="input-group-btn">
                        <button type="button"
                                className="btn btn-default remove-email"><span
                            className="glyphicon glyphicon-remove"></span></button>
                    </div>
                </div>
            );
        });

初始状态(由数据库中的数据填充:

 getInitialState() {
      return {
          name : '',
          description: '',
          emails : [],
          newEmailAddress : ''
      }
    },

根据请求,这里是渲染方法(它需要一个getContent方法。getcontent方法在那里是因为在meteor中我需要等待数据,所以同时我需要一个加载状态。

   getContent() {
        return (

            <div className="box box-success">
                <div className="box-header with-border">
                    <h3 className="box-title">List of emails</h3>
                </div>
                <form role="form" className="form-horizontal">
                    <div className="box-body">
                        <p>Below is a list of email addresses which are added to this email group. If
                            you
                            want
                            to add more
                            you can add them one by one by inputting in the box below or add a list into
                            the
                            same box (email
                            addresses have to be seperated by either a space or ;) then press Add to add
                            to
                            the
                            list. You can edit
                            the addresses directly as well as remove them.</p>
                        <div className="input-group">
                            <input type="text" className="form-control"

                                   value={this.state.newEmailAddress}
                                   onChange={this.handleAddNewEmail}
                                   placeholder="Email addresses seperated by a space or a semicolon ; i.e. test1@test.se;test2@test.se"/>
                    <span className="input-group-btn">
                      <button type="button" onClick={this.handleAddNewEmailButton} className="btn btn-info btn-flat add-email">Add</button>
                    </span>
                        </div>
                        <br/>
                        {this.renderEmail()}
                    </div>
                </form>
            </div>
        )
    },
    render()
    {
    var contentStyle = {
        minHeight : '946px'
    };
        return (
            <div className="content-wrapper" style={contentStyle}>
                <section className="content-header">
                    <h1>
                        {this.data.emailGroup? this.data.emailGroup.name : 'hello'}
                    </h1>
                    <small> Created by: Christian Klinton</small>
                    <br/>
                    <small> Last updated by: Christian Klinton - 2015-11-12 08:10:11</small>
                    <ol className="breadcrumb">
                        <li><a href="/emailGroups"><i className="fa fa-dashboard"></i> Home</a></li>
                        <li><a href="/emailGroups">Email groups</a></li>
                        <li className="active">{this.data.emailGroup? this.data.emailGroup.name : 'loading'}</li>
                    </ol>
                </section>
                <section className="content">
                    <div className="row">
                        <div className="col-md-6">
                            <div className="box box-primary">
                                <div className="box-header with-border">
                                    <h3 className="box-title">Information</h3>

                                </div>
                                <form role="form">
                                    <div className="box-body">
                                        <div className="form-group">
                                            <label htmlFor="inputName">Name</label>
                                            <input type="email" className="form-control" id="name"
                                                   onChange={this.handleNameChange}
                                                   placeholder="Set the name of the email group" autoComplete="off"
                                                  value={this.state.name}/>
                                        </div>

                                        <div className="form-group">
                                            <label>Description</label>
                                    <textarea className="form-control" rows="3" id="description"
                                              placeholder="Enter a description what and how the template is used..."
                                              onChange={this.handleDesriptionChange}
                                              value={this.state.description}
                                    ></textarea>
                                        </div>


                                    </div>
                                </form>
                            </div>
                        </div>
                        <div className="col-md-6">
                            {this.data.emailGroup? this.getContent() : <p>Loading</p> }
                        </div>
                        <div className="form-group">
                            <div className="col-sm-offset-8 col-sm-4">
                                <div className="pull-right">
                                    <button className="btn btn-primary">Delete all</button>
                                    <button className="btn btn-primary save">Save</button>
                                </div>
                            </div>
                        </div>
                    </div>
                </section>
            </div>
        )
    }

【问题讨论】:

  • 你想在哪里渲染它?你的render 方法在哪里?
  • @Mathletics 添加了渲染方法,它有点长,但你明白了要点。

标签: javascript meteor reactjs


【解决方案1】:

您应该将Array.map 直接放在render() 函数中。只需注意每个数组元素都包含在父元素中(此处为&lt;div&gt;)并且必须具有唯一的key={}

class ArrayMap extends React.Component{
  //your functions
  handleEmailChanged(key){
    // Handle email
  }
  render(){
    return(
      <div>
        {
          this.data.emailGroup.emails.map((email) => {
            <div key={email.key}>
              <button onClick={this.handleEmailChanged.bind(this,email.key)}/>
            </div>
          });
        }
      </div>
    );
  }
}

【讨论】:

  • 我更新了我的问题,使其更加清晰。它的 onChange 事件/值绑定我需要在 map 函数中的帮助。顺便说一句,由于流星状态,我需要在单独的函数中渲染 emailGroup(在渲染中调用)
  • 我更新了我的答案。您将密钥作为参数传递给您的 handleChange 函数。并按照那个键行事。
【解决方案2】:

我相信您正在寻找的是这样的:

MyPage = React.createClass({
  mixins: [ReactMeteorData],

  getMeteorData() {
    // ...
  },

  render() {
    const emails = this.data.emailGroup.emails.map((email) => {
      return (
        <div key={email} className="input-group">
          <input type="text" className="form-control"
                 onChange={this.handleEmailListChange} value={email} />

          <div className="input-group-btn">
            <button type="button"
                    className="btn btn-default remove-email"><span
              className="glyphicon glyphicon-remove" /></button>
          </div>
        </div>
      );
    });

    return <div>
      {emails}
    </div>
  }
});

我将self 更改为this。由于您使用的是 ES6 箭头函数,因此无需分配 self = this。

【讨论】:

  • 这似乎是正确的,但 handleEmailListChange 看起来如何。
  • 特别是 this.data/state 的用法。我显然还没有弄清楚:)
  • 看起来您还有其他一些答案,其中包含一些重要信息。你能把这些拼凑起来得到一个解决方案吗?
  • 我想通了。对任何阅读此内容的人的一个警告是 KEY 不能是电子邮件(这会使您在重新渲染时失去对输入的关注)。相反,键应该是索引。(我猜不能使用电子邮件,因为这会改变,因此反应不知道您选择了哪个)。
  • @Todilo 不,永远不要将key 设为索引(0、1、2 等)。当 React 需要删除或添加项目到列表时,这会搞砸。它必须是一个真正唯一的值,例如 ID、电子邮件地址、全名等。
【解决方案3】:

React 要求你为渲染数组中的每个元素都提供独特的东西,它被称为 key,它是一个属性。

如果您不知道为键分配什么,只需为其分配数组的索引:

this.props.doors.map((door, index) => (
    <div key={index} className="door"></div>
));

以下是适用于您的问题的相同解决方案:

return this.data.emailGroup.emails.map((email, index) => {
    return (
        <div key={index} className="input-group">
            <input type="text"
                   className="form-control"
                   onChange={self.handleEmailListChange.bind(this, index)} value={email}/>
        </div>
    );
});

请注意我如何绑定handleEmailListChange 以接收修改后电子邮件的索引。如果handleEmailListChange 接受一个索引,它可以在状态内更新修改后的电子邮件:

handleEmailListChange: function(index, event) {
    var emails = this.state.emails.slice(); // Make a copy of the emails first.
    emails[index] = event.target.value; // Update it with the modified email.
    this.setState({emails: emails}); // Update the state.
}

【讨论】:

  • 感谢您的广泛回答。没有让它完全工作,因为我对流星使用了反应混合,而且它使用了一种叫做“数据”的东西,我需要弄清楚但它应该在那之后工作。谢谢。
  • @Todilo 不管是什么,如果你先了解 React,你就会成功;)
猜你喜欢
  • 2017-12-13
  • 2020-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 2019-11-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多