警告:列表中的每个 child 都应该有一个唯一的 "key" 属性。即使已经设置了密钥

Warning: Each child in a list should have a unique "key" prop. Even after setting the key already

我在 front-end 中使用 react,在后端使用 node、express 和 mongoose。

我已经在文件中设置了 key={uniqueid} 但我仍然收到错误。

这是完整的错误:

index.js:1 Warning: Each child in a list should have a unique "key" prop.

Check the render method of `ArticleCard`. See  for more information.
    in div (at ArticleCard.js:34)
    in ArticleCard (at Blog.js:24)
    in div (at Blog.js:22)
    in div (at Blog.js:21)
    in Blog (created by Context.Consumer)
    in Route (at App.js:44)
    in Switch (at App.js:38)
    in AuthContextProvider (at App.js:35)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:34)
    in div (at App.js:32)
    in App (at src/index.js:9)
    in StrictMode (at src/index.js:8)
    
index.js:1 Warning: Each child in a list should have a unique "key" prop.

Check the render method of `CreateArticle`. See for more information.
    in option (at CreateArticle.js:92)
    in CreateArticle (created by Context.Consumer)
    in Route (at App.js:42)
    in Switch (at App.js:38)
    in AuthContextProvider (at App.js:35)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:34)
    in div (at App.js:32)
    in App (at src/index.js:9)
    in StrictMode (at src/index.js:8)

这里是ArticleCard.js:

import React, { Component, useState, useEffect} from 'react';
import Cookies from 'js-cookie';
import '../components/CSS/ArticleCard.css'
import { Link, Redirect } from 'react-router-dom';
const axios = require('axios').default;

const ArticleCard = () => {
  const [posts, setPosts] = useState({
    postAll: [{}]
  })

  useEffect(() => {
    axios.get('http://localhost:2000/apiEndpoint/READ')
      .then(res => {
        setPosts({ ...posts,
          postAll: res.data
        })
      })
  }, [])

  const articles = posts.postAll.map(post => {
    const uniqueID = post._id
    return (
      <div key={uniqueID} className='card'>
        <h3>{post.title}</h3>
        <hr/>
        <h4>{post.body}</h4>
        <Link className='button' to={`/blog/page/${uniqueID}`}>Open</Link>
      </div>
    )
  })

  return ( 
    <div className='cardContainer'>
    {
      articles > 0 ? "NO" : articles
    }
    </div>
  )
}

export default ArticleCard

这里是CreateArticle.js:

import { useState } from "react";
import React from 'react';
import axios from 'axios'
import '../CSS/CreateArticle.css'

const CreateArticle=()=>{
    const newData={
        title: '',
        body:'',
        category:'',
        success:'',
        fail:''
    }

    const [data, setData] = useState(newData);
    const [response, setResponse] = useState(newData);
    const [category,setCategory] = useState(['Fashion', 'Food', 'Travel', 'Music', 'Lifestyle', 'Fitness', 'DIY', 'Sports', 'Finance', 'Politics', 'Parenting'])

    const handleSubmit=async (e)=>{
        e.preventDefault()
        await axios.post('http://localhost:2000/apiEndpoint/CREATE', {
            title: data.title,
            body: data.body,
            category:data.category
          },{withCredentials:true},{
            headers: {
                  'Content-Type': 'application/json'
          }})
          .then(function (res) {
            
            if(res.data==='Post Added'){
                console.log('Success:',res)
                setResponse({...response, title:'', body:'',category:'',success: "Post Sucessfully Added"})
                
            }else if(res.data==='JWT authentication failed'){
                setResponse({...response, title:'', body:'',category:'',fail: "You need to login before creating a new post"})
            }else{
                console.log('Erorr', res)
                setResponse({...response, title:res.data.error.title, body:res.data.error.body,category:res.data.error.category,success:''})
            }
            
          })

    }

    const handleChange=(e)=>{
        const {name,value}=e.target
        setData({ ...data, [name]: value });
        
    }
    
    
    return(
        <div className='ninetyPer'>
            <div className='flexit'>
                <h1>Create Post</h1>
                {response.success?(<h5 className='success'>{response.success}</h5>):''}
                {response.fail?(<h5 className='err'>{response.fail}</h5>):''}
                
            <form onSubmit={handleSubmit}>
                <div className='Container'>
                <div className='inputField'>
                        
                        <input name='title' onChange={handleChange} value={data.title} placeholder='Title'></input>
                        {response.title?(<h5 className="err">{response.title}</h5>):''}
                </div>

                <div className='bodyField'>
                    
                    <textarea
                        name='body'
                        onChange={handleChange}
                        value={data.body}
                        placeholder='Write anything'
                    />
                    {response.body?(<h5 className="err">{response.body}</h5>):''}
                </div>
                <div className='selectField'>
                
                <select name='category' value={data.category} onChange={handleChange}>
                    <option value=''>~None Selected~</option>
                    {category.map(cat=>{
                        return(
                            <option value={cat}>{cat}</option>
                            
                        )
                    })
                }
                    
                </select>
                {response.category?(<h5 className="err">{response.category}</h5>):''}
                </div>
                </div>
                <button className='submitBtn'>Submit</button>
                

            </form>
            </div>
        </div>

    )
}

export default CreateArticle

如果您需要任何其他文件来查找问题,我会用它更新我的 post。

更新: 我检查了 console.log(uniqueID)。起初,它给了我 UNDEFINED 但另一次它给了我 ID。我不知道为什么一开始它有 UNDEFINED,即使我检查了数据库中的数据并且它们都有单独的唯一 ID。

我认为问题是 const uniqueID = post._id。您必须打印 (console.log(post._id)) 才能看到此值不为空或不重复。也在:

<select name='category' value={data.category} onChange={handleChange}>
  <option value=''>~None Selected~</option>
     {category.map(cat=>{
        return(
           <option value={cat}>{cat}</option>
        )
      })
  }

您需要指定一个键值

 <option key={[uniquevalue]} value={cat}>{cat}</option>

ArticleCard.js 中使用 console.log(uniqueID) 检查 id 是否有任何值或显示未定义。

如果值显示未定义,则尝试检查传递该 ID 的代码。

如果uniqueID显示一些值那么可能有两种可能性 检查 ID 是否与其他 ID 不匹配,或者您是否使用任何删除 post 选项

如果在删除任何 post 后添加 post 时崩溃,则检查您是否正在增加 ID,如果是的话,ID 匹配项可能已经存在

文件ArticleCard.js

选项 1:

import React, { useState, useEffect, useMemo } from 'react';
import Cookies from 'js-cookie';
import '../components/CSS/ArticleCard.css'
import { Link, Redirect } from 'react-router-dom';

const axios = require('axios').default;

const ArticleCard = () => {
  const [posts, setPosts] = useState({
    postAll: [] // remove the empty object from the state initialization
  });

  useEffect(() => {
    axios.get('http://localhost:2000/apiEndpoint/READ')
      .then(res => {
        setPosts({
          ...posts,
          postAll: res.data
        })
      })
  }, [])
    
  /*
   * check whether there are posts; if not, 'articles' will be null
   * NOTE: useMemo aim is to avoid recalculating 'articles' at each re-render
   *       unless 'posts.postAll' has changed.
   */
  const articles = useMemo(() => {
    if (posts.postAll.length === 0) return null;
    
    return posts.postAll.map(post => {
      const uniqueID = post._id;
      return (
        <div key={uniqueID} className='card'>
          <h3>{post.title}</h3>
          <hr />
          <h4>{post.body}</h4>
          <Link className='button' to={`/blog/page/${uniqueID}`}>Open</Link>
        </div>
      );
    });
  }, [posts.postAll]);

  return (
    <div className='cardContainer'>
        {articles ? articles : "NO"}
    </div>
  );
}

export default ArticleCard;

选项 2:去掉 'articles' const

import React, { useState, useEffect } from 'react';
import Cookies from 'js-cookie';
import '../components/CSS/ArticleCard.css'
import { Link, Redirect } from 'react-router-dom';

const axios = require('axios').default;

const ArticleCard = () => {
  const [posts, setPosts] = useState({
    postAll: [] // remove the empty object from the state initialization
  });

  useEffect(() => {
    axios.get('http://localhost:2000/apiEndpoint/READ')
      .then(res => {
        setPosts({
          ...posts,
          postAll: res.data
        })
      })
  }, [])

  return (
    <div className='cardContainer'>
        {posts.postAll.length === 0 ? "NO" : (
        posts.postAll.map(post => {
          const uniqueID = post._id;
          return (
            <div key={uniqueID} className='card'>
              <h3>{post.title}</h3>
              <hr />
              <h4>{post.body}</h4>
              <Link className='button' to={`/blog/page/${uniqueID}`}>Open</Link>
            </div>
          );
        });
      )
    </div>
  );
}

export default ArticleCard;

文件CreateArticle.js

...
<select name='category' value={data.category} onChange={handleChange}>
  <option value=''>~None Selected~</option>
    {category.map(cat=>{
      return (
        <option key='add_the_key_here' value={cat}>{cat}</option>
      );
    })}
</select>
...