Предупреждение: у каждого дочернего элемента в списке должна быть уникальная «ключевая» опора. Даже после установки ключа уже

#javascript #html #reactjs #react-context #react-key-index

#javascript #HTML #reactjs #реагировать-контекст #реагировать-ключ-индекс

Вопрос:

Я использую 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
  

Если вам потребуется какой-либо другой файл для поиска проблемы, я обновлю свой пост с его помощью.

Обновление: я проверил с помощью console.log (UniqueID). Сначала он дает мне UNDEFINED, но в другой раз он дает идентификатор. Я не знаю, почему именно сначала он не ОПРЕДЕЛЕН, хотя я проверил данные в БД, и все они имеют отдельные уникальные идентификаторы.

Комментарии:

1. это выглядит правильно. _id может быть, не определено?

2. В вашем CreateArticle.js вы не устанавливаете key атрибут для option файлов, сгенерированных category.map( cat => { ... })

3. При использовании фрагментов стека рекомендуется нажать «Выполнить фрагмент кода», чтобы посмотреть, демонстрирует ли он что-нибудь интересное. Если нет, вам следует рассмотреть возможность использования кнопки форматирования кода (выглядит как {} ) вместо этого.

4. Спасибо, Секан, я исправил это, и эта ошибка исчезла, однако та, что в ArticleCard.js у меня все еще есть ошибка. 1 ошибка. осталось 1.

5. Вторая ошибка, вероятно, связана с тем, что вы извлекаете сообщения с помощью асинхронной операции и пытаетесь отобразить через posts.postAll whet, который он все еще содержит, [{}] поэтому post._id не определено. Я собираюсь опубликовать исправление в ответах, так как в комментариях нет места. 😉

Ответ №1:

Я думаю, что проблема в 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>
  

Комментарии:

1. Спасибо за ответ. Я проверил с помощью console.log (UniqueID). Сначала он дает мне UNDEFINED, но в другой раз он дает идентификатор. Я не знаю, почему именно сначала он не ОПРЕДЕЛЕН, хотя я проверил данные в БД, и все они имеют отдельные уникальные идентификаторы

2. Что касается другого в category.map, я присвоил ID тому же значению, что и строка в моем useState, поскольку все они уникальны.

Ответ №2:

Файл 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’

 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>
...
  

Ответ №3:

ArticleCard.js Используется console.log(uniqueID) для проверки, имеет ли id какое-либо значение или оно показывает undefined.

Если значение отображается как неопределенное, попробуйте проверить код, из которого вы передаете этот идентификатор.

Если uniqueID отображается какое-то значение, то может быть две возможности проверить, что идентификатор не совпадает с другим, или если вы используете какую-либо опцию удаления записи

Если он рухнет при добавлении сообщения после удаления любого сообщения, проверьте, увеличиваете ли вы идентификатор, если да, может быть вероятность, что совпадение идентификаторов уже существует

Комментарии:

1. Спасибо за ответ. Я проверил с помощью console.log (UniqueID). Сначала он дает мне UNDEFINED, но в другой раз он дает идентификатор. Я не знаю, почему именно сначала он не ОПРЕДЕЛЕН, хотя я проверил данные в БД, и все они имеют отдельные уникальные идентификаторы