簡體   English   中英

盡管有創建唯一鍵的方法,但列表中的每個孩子都應該有一個唯一的“鍵”道具錯誤

[英]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}>&#x2935;</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">&#x2945;</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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM