![](/img/trans.png)
[英]"Each child in a list should have a unique 'key' prop error" despite having a key
[英]Each child in a list should have a unique "key" prop error despite method to create unique key
在我的應用程序中,我目前收到反應警告:
警告:列表中的每個孩子都應該有一個唯一的“關鍵”道具。
檢查GetReplies
的渲染方法。
這是 GetReplies 方法:
export function GetReplies(props) {
const Id = props.Id;
const replies = allComments.filter(obj => obj.ParentCommentId === Id).
sort((objA, objB) => new Date(objB.Time) - new Date(objA.Time));
console.log(generateKey(Id));
if (Object.keys(replies).length !== 0) {
return (
<div key = {"replies-container-" + generateKey(Id)} id={"replies-container-" + Id} className="replies-container">
<div key ={"panel-heading replies-title" + generateKey(Id)} className="panel-heading replies-title">
<a key = {"accordion-toggle replies-" + generateKey(Id)} className="accordion-toggle replies-a collapsed" data-parent={"#replies-container-" + Id} data-toggle="collapse" data-target={"#replies-for-" + Id}>Replies</a>
</div>
<div key = {"replies-for-" + Id} id={"replies-for-" + generateKey(Id)} className="replies-list collapse">
{
<React.Fragment>
{ Object.entries(replies).reverse().map(([key, arr]) => {
return (
<GetComments commentsArray = {replies}/>
)
}) }
</React.Fragment>
}
</div>
</div>
);
}
}
這是它調用的 GetComments 方法:
export function GetComments({ commentsArray }) {
return (
<React.Fragment>
{commentsArray.map((comment) => {
const localId = comment.LocalId;
const parentCommentId = comment.ParentCommentId;
const parentLocalId = allComments.filter(obj => obj.Id === parentCommentId);
const recipients = comment.Recipients;
let recipientsArray = [];
let recipientsList;
recipients.forEach(function (arrayItem) {
recipientsArray.push(arrayItem.Name);
recipientsList = recipientsArray.join(', ');
});
console.log(generateKey(localId));
const date = new Date(comment.Time);
const formattedDate = date.toLocaleDateString() + " " + ("0" + date.getHours()).slice(-2) + ":" + ("0" + date.getMinutes()).slice(-2);
return (
<div key={generateKey(localId)} className="comment-container">
<div key={generateKey(comment.Commenter.ItemId)} className="commenter">
<span className="id-label">{localId}</span>
{parentCommentId && (
<span className="reply" title={`in reply to ${parentLocalId[0].LocalId}`}>
<a className="reply" href={"#c" + parentLocalId[0].LocalId}>⤵</a> </span>
)}
<span><a id={"c" + localId} name={"c" + localId}>{comment.Commenter.Name}</a></span>
<div key={generateKey(localId) + "-comment-actions-container "} className="comment-actions-container">
<button type="button" className="btn-reply" data-value={comment.Id} title="Reply to comment" data-toggle="modal" data-target="#dlg-new-comment">⥅</button>
</div>
</div>
<div key={generateKey(localId) + "-recipients "} className="recipients">{recipientsList}</div>
<div key={generateKey(localId) + "-comment "} className="comment">{comment.Comment}</div>
<div key={generateKey(localId) + "-comment-footer "} className="comment-footer">{formattedDate}</div>
<GetReplies Id = {comment.Id}/>
</div>
);
})}
</React.Fragment>
);
}
為了幫助確保每個密鑰都是唯一的,我做了這個生成密鑰方法:
const generateKey = (pre) => {
return `${ pre }_${ new Date().getTime() }`;
}
但是我仍然收到那個獨特的密鑰錯誤,我不知道我可能會丟失什么?
我什至試圖通過這樣做來擴展它:
const generateKey = (pre) => {
let index =0;
return `${ pre }_${ new Date().getTime()}_${index++}`;
}
但索引總是等於0? 所以我不確定為什么這也沒有增加,任何建議都將不勝感激
您應該使用commentsArray.map
的索引
喜歡:
{commentsArray.map((comment, index) => {
...
key={generateKey(Id, index)}
接着:
const generateKey = (pre, index) => `${pre}_${index}`;
您正在使用Id
值進行過濾,因此每個孩子的鍵都是相同的,這就是您需要 commentsArray 索引的原因。
即使您的 generateKey 可能有效(但不確定,因為它會在映射到數組時很快被調用),但您將密鑰添加到代碼的錯誤部分。 React 期望 for 循環中的每個項目都有一個鍵。 在您的情況下,您已經為每個 JSX 元素添加了一個鍵,除了Object.entries(replies).reverse().map
的那些
您可能可以通過在其中添加密鑰來解決您的問題,如下所示:
{Object.entries(replies).reverse().map(([key, arr]) => {
return (
<GetComments key={key} commentsArray = {replies}/>
)
})}
不過,要添加注釋,React 使用鍵值來識別重新渲染時的更改。 如果您的數組被重新排序,它可以使用鍵來防止大量重新渲染。 這里的最佳做法是添加與數據本身相關的密鑰,而不是數組中的位置或隨機數。
除了上一個答案:
const generateKey = (pre) => {
let index =0;
return `${ pre }_${ new Date().getTime()}_${index++}`;
}
將始終有一個 0 索引,因為每個 function 調用都會創建自己的 scope,並帶有自己的“索引”變量。 要在每次調用中增加索引,您必須在 function 之外提取“索引”變量,因此每個 function 調用將共享相同的索引變量,從“外部”Z31A1FD140BE4BEF2D11E121EC1 索引仍然是最佳索引您沒有可以從數據中使用的唯一密鑰)。
使用“new Date().getTime()”來生成密鑰也是一個壞主意,因為您的代碼將運行得如此之快,以至於一些組件可以(並且將)共享相同的時間戳。
另一種方法是使用第三方庫,如“uuid”,生成唯一 ID,但必須謹慎使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.