我一直在努力
ReactJS demo for ASP.NET Core
我正在纠结一条错误信息:
警告:数组或迭代器中的每个子项都应具有唯一的“键”属性。
检查的渲染方法
CommentList
.有关详细信息,请参阅url。
在注释中(由commentlist创建)
在CommentList中(由CommentBox创建)
在div中(由commentbox创建)
在评论框中
消息很清楚,数组中的每个子都需要一个密钥。代码分配了一个键,并且已经下载了Chrome I的反应控制台,也可以看到数组和添加的所有数据。
在我的代码中,我有以下内容:
class CommentList extends React.Component {
render() {
const commentNodes = this.props.data.map(comment => (
<Comment author={comment.author} key={comment.id}>
{comment.author}
</Comment>
));
return (
<div className="commentList">
{commentNodes}
</div>
);
}
}
您可以看到键被分配给comment组件并返回到comment列表。这个
id
似乎不是空的,所以我很困惑为什么我仍然收到这个错误消息。
你能帮我解决这个问题吗?
这是我目前为止的完整源代码:
js/应用程序jsx
class CommentBox extends React.Component {
constructor(props) {
super(props);
this.state = { data: [] };
this.handleCommentSubmit = this.handleCommentSubmit.bind(this);
}
loadCommentsFromServer() {
const xhr = new XMLHttpRequest();
xhr.open('get', this.props.url, true);
xhr.onload = () => {
const data = JSON.parse(xhr.responseText);
this.setState({ data: data });
};
xhr.send();
}
handleCommentSubmit(comment) {
const comments = this.state.data;
// Optimistically set an id on the new comment. It will be replaced by an
// id generated by the server. In a production application you would likely
// use a more robust system for ID generation.
comment.Id = comments.length + 1;
const newComments = comments.concat([comment]);
this.setState({ data: newComments });
const data = new FormData();
data.append('author', comment.author);
data.append('text', comment.text);
const xhr = new XMLHttpRequest();
xhr.open('post', this.props.submitUrl, true);
xhr.onload = () => this.loadCommentsFromServer();
xhr.send(data);
}
componentDidMount() {
this.loadCommentsFromServer();
window.setInterval(() => this.loadCommentsFromServer(), this.props.pollInterval);
}
render() {
return (
<div className="commentBox card">
<h4>Comments</h4>
<CommentList data={this.state.data} />
<CommentForm onCommentSubmit={this.handleCommentSubmit} />
</div>
);
}
}
class CommentList extends React.Component {
render() {
const commentNodes = this.props.data.map(comment => (
<Comment author={comment.author} key={comment.id}>
{comment.author}
</Comment>
));
return (
<div className="commentList">
{commentNodes}
</div>
);
}
}
class CommentForm extends React.Component {
constructor(props) {
super(props);
//Initial state?
this.state = { author: '', text: '' };
//Event handlers
this.handleAuthorChange = this.handleAuthorChange.bind(this);
this.handleTextChange = this.handleTextChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleAuthorChange(e) {
this.setState({ author: e.target.value });
}
handleTextChange(e) {
this.setState({ text: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
const author = this.state.author.trim();
const text = this.state.text.trim();
//If inputs are null then return nothing.
if (!text || !author) {
return;
}
//Post data to the server
this.props.onCommentSubmit({ author: author, text: text });
//Clear form
this.setState({ author: '', text: '' });
}
render() {
return (
<div className="commentForm">
<form className="commentForm" onSubmit={this.handleSubmit}>
<input type="text" placeholder="Your name" value={this.state.author} onChange={this.handleAuthorChange} />
<input type="text" placeholder="Say something..." value={this.state.text} onChange={this.handleTextChange} />
<input type="submit" value="Post" />
</form>
</div>
);
}
}
class Comment extends React.Component {
render() {
return (
<div className="comment">
<p className="commentAuthor">
{this.props.author}
</p>
</div>
);
}
}
ReactDOM.render(
<CommentBox url="/comments" submitUrl="/comments/new" pollInterval={2000} />,
document.getElementById('content')
);
我正在为我的数据使用一个模型,因为我稍后将向存储库介绍这个模型。
模型/注释模型
namespace ReactDemo.Models
{
public class CommentModel
{
public int Id { get; set; }
public string Author { get; set; }
public string Text { get; set; }
}
}
控制器/家庭控制器
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using ReactDemo.Models;
namespace ReactDemo.Controllers
{
public class HomeController : Controller
{
private static readonly IList<CommentModel> _comments;
static HomeController()
{
_comments = new List<CommentModel>
{
new CommentModel
{
Id = 1,
Author = "Daniel Lo Nigro",
Text = "Hello ReactJS.NET World!"
},
new CommentModel
{
Id = 2,
Author = "Pete Hunt",
Text = "This is one comment"
},
new CommentModel
{
Id = 3,
Author = "Jordan Walke",
Text = "This is *another* comment"
},
};
}
public IActionResult Index()
{
return View();
}
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
[Route("comments")]
[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
public ActionResult Comments()
{
return Json(_comments);
}
[Route("comments/new")]
[HttpPost]
public ActionResult AddComment(CommentModel comment)
{
// Create a fake ID for this comment
comment.Id = _comments.Count + 1;
_comments.Add(comment);
return Content("Success :)");
}
}
}