简体   繁体   English

在反应中渲染输入数组

[英]Render array of inputs in react

I have an array of emails (as a part of a bigger model). 我有一系列电子邮件(作为更大型号的一部分)。 These are displayed in seperate rows witha remove button for each (the address itself can be updated in the input box directly). 这些显示在单独的行中,每个行都有删除按钮(地址本身可以直接在输入框中更新)。 Unfortunately I dont know how to do this in react when the inputs are renderd using a map function. 不幸的是,当使用map函数渲染输入时,我不知道如何做出反应。 (I am converting a meteor blaze project to meteor react). (我正在将流星火焰项目转换为流星反应)。

Everything renders but how do I attach to change event so I can update my array of emails? 一切都呈现,但我如何附加到更改事件,以便我可以更新我的电子邮件数组? onChange + value need to be set somehow. onChange +值需要以某种方式设置。

This is the map function 这是地图功能

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>
            );
        });

The initial state(which is populated with data from the db: 初始状态(使用db中的数据填充:

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

Upon request here is the render method(it requires a getContent method.The getcontent method is there because in meteor I need to wait for data so in the meantime I need a loading state. 根据请求,这里是render方法(它需要一个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>
        )
    }

React requires you to have something unique for every element in the rendered array, it's called a key , and it's an attribute. React要求你为渲染数组中的每个元素赋予一些独特的东西,它被称为key ,它是一个属性。

If you don't know what to assign to the key, just assign it the array's indexes: 如果您不知道要为键分配什么,只需为其分配数组的索引:

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

Here's the same solution applied to your problem: 以下是适用于您的问题的相同解决方案:

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>
    );
});

Notice how I bound handleEmailListChange to receive the index of the modified email. 请注意我如何绑定handleEmailListChange以接收修改后的电子邮件的索引。 If handleEmailListChange accepts an index, it can update the modified email within the state: 如果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.
}

You should place your Array.map directly inside your render() function. 您应该将Array.map直接放在render()函数中。 Just take care that each array element is wrapped inside a parent element ( <div> here) and must have a unique key={} 请注意每个数组元素都包含在父元素(此处为<div> )内,并且必须具有唯一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>
    );
  }
}

I believe what you're looking for is something like this: 我相信你要找的是这样的:

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>
  }
});

I changed self to this . 我改变了selfthis Since you're using the ES6 arrow function, there's no need to assign self = this . 由于您使用的是ES6箭头功能,因此无需指定self = this

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM