Предупреждение: каждый дочерний элемент в списке должен иметь уникальный «ключевой» реквизит, даже если он имеет уникальный ключ React

#javascript #reactjs

#javascript #reactjs

Вопрос:

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

 import React, { useEffect, useRef } from "react";
import fire from "./firebase";
import firebase from "firebase"
import { useState } from "react"
import Header from "./header"
import Nav from "./nav"
import { NavLink, Redirect } from "react-router-dom";
import AudioPlayer from "./audioplayer"   

const Music = ({ match }) => {
    const audioRef = useRef();
    const audioPlayer = audioRef.current
    const [audioSrc, setAudioSrc] = useState()
    const [musics, setMusics] = useState([])
    const [user, setUser] = useState(null)
    const [pfp, setPfp] = useState(null)
    const [audioTitle, setAudioTitle] = useState(null)
    const { params: { uID } } = match;
    var userName;
    var tracksTitle = [];
    useEffect(()=>{
        firebase.database().ref("users/" uID "/praivate/login credentials").on("value", (snapshot)=>{
            setUser(snapshot.val().userName)
            setUser(snapshot.val().userName)
        })
        firebase.database().ref("users/" uID "/public/profile/pic").on("value", (snapshot)=>{
            console.log(snapshot.val().pfpUrl)
            setPfp(snapshot.val().pfpUrl)
        })
    }, [])
    var music;

    //maybe the problem is over here somewhere
    useEffect(()=>{
        firebase.database().ref("users/" uID "/public/songs/").on("value", (snapshot)=>{
            //stores data in music.
            music = snapshot.val()
            //gets all title of the data
            Object.values(music).forEach((value)=>{  
                tracksTitle.push(value.title)//pushes titles to tracksTitle
            })
            setMusics(tracksTitle) //stores all track title in musics
        })
       
    }, [uID])

    const [progVal, setProgVal] = useState("0%")
    function update(event){
        let duration = (event.target.currentTime/event.target.duration)*100
        setProgVal(duration)
    }
    
    function play(event){
        const value = event.target.getAttribute("value")
        console.log(value)
        if(value){
            firebase.database().ref("public/songs/" value).on("value", (snapshot)=>{
                setAudioSrc(snapshot.val().aduioURL)
            })
        }
        setAudioTitle(value)
        audioPlayer.play()
        
    }

    function playAudio(){
        audioPlayer.play()
    }

    

    function stop(event){
        audioPlayer.pause()
    }

   
    
    return(
        <>
            <Nav />
            <div id = "profile" className = "main">
                <audio id = "player" ref = {audioRef} src = {audioSrc} name = "audioplayer" onTimeUpdate = {update}>
                </audio>
                <div class = "profile-container">
                    <div className = "cover-pic">
                        <img src = "" />
                        <div className = "pfp">
                            <img src = {pfp} height = "100" width = "100"/>
                        </div>
                        <div className = "User-Name">
                            <h1>{user}</h1>
                        </div>
                    </div>
                    <div class = "tabsContainer">
                    <div class = "tabs-holder">
                    <NavLink to = {"/u/" uID "/music"}><button><span>Music</span></button></NavLink>
                        <button><span>Playlist</span></button>
                        <button><span>About</span></button>
                    </div>
                </div>
                </div>
               
                <div class = "music-content-container">
                    <div class = "music-box">
                        <div class = "user-musics">
                            <ul>
                                {musics amp;amp; musics.map((name, i)=>{
                                    console.log()
                                    return(
                                        <>
                                            //it does not render the third array properly
                                            <li key = {i}><button onClick = {play} value = {name}>Play</button>{name}</li>
                                        </>
                                    )
                                })}
                            </ul>
                        </div>
                    </div>
                </div>
                
            </div>
            <AudioPlayer progVal = {progVal} stop = {stop} playAudio = {playAudio}/>
            <Header />
        </>
    )
    }  
export default Music
// 

Не могли бы вы, ребята, помочь мне разобраться в проблеме, заранее спасибо.

обновление: мои данные из firebase выглядят так:

введите описание изображения здесь

и этот код выберет заголовок каждого данные

 useEffect(()=>{
        firebase.database().ref("users/" uID "/public/songs/").on("value", (snapshot)=>{
            //stores data in music.
            music = snapshot.val()
            console.log(music)
            //gets all title of the data
            Object.values(music).forEach((value)=>{ 
                 
                tracksTitle.push(value.title)//pushes titles to tracksTitle
            })
            setMusics(tracksTitle) //stores all track in musics
        }) 

введите описание изображения здесь

кнопка «fikka fikka» даже не работает, когда я навожу курсор на «fikka fikka», она даже не меняет курсор на текстовый курсор, в то время как в ed sheeran и one direction у нее нет этой проблемы

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

1. Для одного вы используете индекс массива в качестве ключа. Это вызовет проблемы. Если песни имеют уникальные имена, вы можете использовать само имя в качестве ключа. Ваше использование фрагментов также проблематично. В этом случае использование фрагментов практически не имеет смысла.

2. @Laras спасибо, я пробовал это, но я не знаю почему, третий отображаемый элемент отображается неправильно, я не могу выделить текст и тоже не могу нажать на кнопку.

3. Итак, если я правильно читаю, musics это просто массив заголовков? Устранена ли ошибка ключа react с помощью одного из решений, представленных здесь? Можете ли вы немного подробнее описать, что вы имеете в виду, что 3-й элемент списка не работает? Это только 3-й? (1-й, 2-й, 4-й, 5-й и т. Д. Все работают?) Если проблема с ключом react решена, и у вас появилась новая ошибка, могу ли я предложить задать новый вопрос для новой проблемы?

4. В этом последнем скриншоте кажется, что сопоставление li элементов сработало точно так, как ожидалось. Похоже, что что- то (невидимый элемент) перекрывает ваш пользовательский интерфейс и не позволяет проходить клики. Вы также проверили DOM, чтобы увидеть, что все отображается на экране?

5. Ну, сами элементы списка не имеют присвоенных им имен классов, но я имел в виду больше всего остального в пользовательском интерфейсе, который может закрывать их от мыши, т. Е. Некоторые невидимые, абсолютно позиционированные элементы.

Ответ №1:

Ключи React должны находиться на самом внешнем возвращаемом элементе из сопоставления.

 {musics amp;amp; musics.map((name, i)=>{
  return(
  <Fragment key={i}>
    //it does not render the third array properly
    <li>
      <button onClick={play} value={name}>Play</button>
      {name}
    </li>
  </Fragment>)
})}
 

Обратите внимание, что для этого сокращение фрагмента react несовместимо, вы должны использовать Fragment компонент. Или, поскольку существует только один элемент Fragment , который в основном бесполезен, удалите его и поместите ключ li туда, где он был.

 {musics amp;amp; musics.map((name, i)=>{
  return(
  <li key={i}>
    <button onClick={play} value={name}>Play</button>
    {name}
  </li>)
})}
 

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

1. Это решение также использует индекс в массиве в качестве ключа, что категорически не рекомендуется в React.

2. @LarsHoldaas не рекомендуется, да, запрещено, совсем нет. Он соответствует критериям приемлемости для использования, т. Е. Не похоже, что массив переупорядочивается или элементы добавляются / удаляются. Из того, что я могу сказать, элементы массива просто переключают состояние воспроизведения. Вопрос OP не об этом.

3. @DjBilljeOfficial musics Правильно ли сформирован ваш массив состояний? Для меня это подразумевает проблему целостности данных, не связанную с ключами react. Пожалуйста, поделитесь значением musics массива. Думаете, вы могли бы создать работающий codesandbox, который воспроизводит проблему пользовательского интерфейса, и поделиться ссылкой в вашем вопросе?

4. @DjBilljeOfficial давайте начнем с исключения. Удалите код, который идет после кнопок. <AudioPlayer И <Header /> . На случай, если у них есть какой-то странный css, который его блокирует.

5. Пожалуйста, я думаю, что это обсуждение отладки должно происходить в разделе основных комментариев.