Javascript 在反应中渲染输入数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34321128/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Render array of inputs in react
提问by Todilo
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. (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:
初始状态(用数据库中的数据填充:
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.
根据请求,这里是渲染方法(它需要一个 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. [email protected];[email protected]"/>
<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>
)
}
回答by Moshe Revah
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 要求你对渲染数组中的每个元素都有一些独特的东西,它被称为 a 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. If handleEmailListChange
accepts an index, it can update the modified email within the state:
请注意我如何绑定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.
}
回答by Naisheel Verdhan
You should place your Array.map
directly inside your render()
function. Just take care that each array element is wrapped inside a parent element (<div>
here) and must have a unique key={}
你应该把你的Array.map
直接放在你的render()
函数中。只需注意每个数组元素都包含在父元素(<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>
);
}
}
回答by ffxsam
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
. Since you're using the ES6 arrow function, there's no need to assign self = this
.
我换self
到this
。由于您使用的是 ES6 箭头函数,因此无需将self = this
.