1
votes

Im working on a react lobby for a card game that looks like this: Lobby Image

Each name and "kick" button is a react component that I render based off of a list of names (ALL THE NAMES IN THIS LIST ARE UNIQUE). I figured that since the names are unique, I could use the names as a key, but for some reason i am getting the following error: Error Message

What am I doing wrong here?

Note: I also tried doing key = {player + "1"} for the KickButton key to make it unique from its respective PlayerIcon but the error remains

import React from 'react';
import firebase from "./firebase.js";

class PlayerIcon extends React.Component{

    render() {
        return(
            <div>
                <h1>{this.props.name}</h1>
            </div>
        )
    }
}

class KickButton extends React.Component {
    constructor(props){
        super();
        this.state = {
            style: props.style,
            player: props.kicked,
            Lobbycode: props.Lobbycode
        }
        this.handleKick = this.handleKick.bind(this)
    }

    handleKick() {
        var firestore = firebase.firestore();  
        var docRef = firestore.doc("Games/Game " + this.state.Lobbycode);
        const confirmed = window.confirm("Do you want to kick " + this.state.player + "?");
        if (confirmed) {
            docRef.get()
                .then((docSnapshot) => {
                    if (docSnapshot.data().PlayerAmnt === 1) {
                        firestore.doc("Games/Active Games").update({
                            "Active Games" : firebase.firestore.FieldValue.arrayRemove(this.state.Lobbycode)
                        })
                        firestore.doc("Games/Game " + this.state.Lobbycode).delete();
                    } else {
                        docRef.update({
                            players : firebase.firestore.FieldValue.arrayRemove(this.state.player),
                            PlayerAmnt : firebase.firestore.FieldValue.increment(-1)
                        }) 
                    }
                })
            return;
        }
    }

    render(props) {
        return <button onClick = {this.handleKick} style = {this.state.style}>Kick</button>
    }
}

class HostLobbylist extends React.Component {

    render() {
        var playerstorender = [<div style={{display: "flex"}}><PlayerIcon key={this.props.players[0]} name={this.props.players[0]}/></div>].concat(
            this.props.players.slice(1).map(player => 
                <div style={{display: "flex"}}>
                <PlayerIcon key={player} name={player}/><KickButton key={player} kicked={player} style={{fontSize: "20px", height: "30px", verticalAlign: "middle", margin:"25px"}} Lobbycode={this.props.Lobbycode}/>
            </div>))

    return(
        <div>
            {playerstorender} 
        </div>   
    ) 
}
}

export default HostLobbylist

EDIT 1: Below is my new render function where the key is in the parent div, but the error is still there. Am I still misunderstanding?

class HostLobbylist extends React.Component {

 render() {
     var playerstorender = [<div key={this.props.players[0]} style={{display: "flex"}}><PlayerIcon name={this.props.players[0]}/></div>].concat(
         this.props.players.slice(1).map(player => 
             <div key={player} style={{display: "flex"}}>
             <PlayerIcon name={player}/><KickButton kicked={player} style={{fontSize: "20px", height: "30px", verticalAlign: "middle", margin:"25px"}} Lobbycode={this.props.Lobbycode}/>
         </div>))

 return(
     <div>
         {playerstorender} 
     </div>   
 ) 
}
}

EDIT 2: I found the error!!!!! this.props.players sometimes had 0 items so the key for the first item in players to render was undefinded i guess. Thank you for the help!

1
The key needs to be in the parent element of the return, not on the PlayerIcon component. .map(player =><div key={player} style={{display: "flex"}}><PlayerIcon name={player}/>...pilchard
@pilchard My edit shows my new render, but the error is still there, am i still doing something wrong?Seb
Is player an object? or a string value?HichamELBSI
@HichamELBSI it is a string valueSeb
@HichamELBSI I found the error, thank you for pointing me in the right direction!Seb

1 Answers

-1
votes

You can add an index that increments at every loop, and you use this index as a key to differentiate your elements from the loop

this.props.players.slice(1).map((player, index) => 
                <div key={index} style={{display: "flex"}}>