Предупреждение: каждый дочерний элемент в списке должен иметь уникальную "ключевую" опору. Даже после установки ключа уже
Я использую реакцию во внешнем интерфейсе и node, express и mongoose в серверной части.
Я уже ввел ключ ={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
Если вам потребуется какой-либо другой файл, чтобы найти проблему, я обновлю свой пост.
Обновление: я проверил console.log(uniqueID). Сначала он дает мне НЕОПРЕДЕЛЕННОЕ, но в другой раз дает идентификатор. Я не знаю, почему сначала он НЕ ОПРЕДЕЛЕН, хотя я проверил данные в БД, и все они имеют отдельные уникальные идентификаторы.
3 ответа
Файл 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: избавиться от константы "статьи"
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>
...
Я думаю, что это проблема 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 какое-либо значение или он показывает undefined.
Если значение показывает undefined, попробуйте проверить код, из которого вы передаете этот идентификатор.
Если
uniqueID
показывает какое-то значение, тогда может быть две возможности проверить, что идентификатор не совпадает с другим, или если вы используете любую опцию удаления публикации
Если его коллапс при добавлении публикации после удаления любого сообщения, проверьте, увеличиваете ли вы идентификатор, если да, может быть вероятность, что совпадение идентификатора уже существует.