Pat Rick
Pat Rick

Reputation: 33

Unique Key Props

Hello I have been working on a React app for some time. Since the beginning, the famous error message:Each child in a list should have a unique "key" prop I am not sure where exactly I have to implement the key, because I don't have a real list element. I already tried to give all components in the TodoTable.js a unique key but that didn't change the error message- Please help me.

import React from "react";
import { InputBar } from "./InputBar";
import { Todo } from "./Todo";

const emptyForm = {
  enterTodo: ""
  
};

export class TodoTable extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        enterTodo: "",
        todos: this.props.todos,
        status: 'open'
      };
      this.handleEnterTodo = this.handleEnterTodo.bind(this);
      this.handleStatus = this.handleStatus.bind(this);
      this.handleCreateTodo = this.handleCreateTodo.bind(this);
      this.handleClearTodos = this.handleClearTodos.bind(this);
      this.handleDeleteTodo = this.handleDeleteTodo.bind(this);
 
    }
    //Textbox Input handler
    handleEnterTodo(event) {
      
      this.setState({
        enterTodo: event.target.value
      });
    }
    //Status handler
    handleStatus(event) {
      let status;
      const changeState = event.status == 'done' ? status = 'open' : status = 'done';
      
      //Verkürzen Copy State
      let todo = event;
      todo.status = status;
      
      this.setState({ todo });
    }

    //delete todo
    handleDeleteTodo(event) {
      let todo = this.state.todos;
      todo.splice(this.state.todos.indexOf(event), 1)
    
      this.setState({ todo });
    }
   
    //Create Todo
    handleCreateTodo(event) {
      const todo = {
        id: this.state.todos.length,
        describtion: this.state.enterTodo,
        status: 'open'
      };

        this.setState({
          todos: [todo, ...this.state.todos]
        })
        this.state.enterTodo = emptyForm.enterTodo; // Überarbeiten
      
    }

    //Clear Todo List 
    handleClearTodos(event) {
      let CleanedTodos = []
      
      this.state.todos.forEach((element, index) => {

        if(this.state.todos[index].status == 'open'){
            CleanedTodos.push(this.state.todos[index]);
        } 
        
      });

      this.setState({ 
        todos: CleanedTodos
       });
    }

    render() {

      return (

        <>
          <InputBar

            handleCreateTodo={ this.handleCreateTodo }
            handleEnterTodo={ this.handleEnterTodo }
            enterTodo={ this.state.enterTodo }
            handleClearTodos={ this.handleClearTodos }
          />
          <Todo

            handleStatus={ this.handleStatus }
           
            todos={ this.state.todos }
            handleClearTodos={ this.state.handleClearTodos }
            handleDeleteTodo= { this.handleDeleteTodo }
          />
        </>
      );
    }
  }

This is my first Component for todos

import React from "react";
import { FormButton } from "./FormButton";

export class Todo extends React.Component {
    render() {
      const openTodo = [];
      const doneTodo = [];
      const lineBreak = <hr></hr>
      const todoList = 
      [ 
        openTodo,
        lineBreak,
        doneTodo
      ];

      //Select Open Todo and Done
      this.props.todos.forEach((element, index) => {
        if(this.props.todos[index].status == 'open'){
    
          let todoOpen = (
            //CSS Clases for design open 
            <div className="openTodos">
              {this.props.todos[index].describtion}

              <FormButton lable='' onClick= {() => this.props.handleStatus(this.props.todos[index])}/>
              <FormButton lable='' onClick= {() => this.props.handleDeleteTodo(this.props.todos[index])}/>
              
            </div>
          );
          //Push open Todo in Open Array
          todoList[0].push(todoOpen); 
        } 
        else{
         
          let todoDone = (
            //CSS Clases for design open 
            <div className="doneTodos">
              {this.props.todos[index].describtion}
              <FormButton lable='' onClick= {() => this.props.handleStatus(this.props.todos[index])}/>
              <FormButton lable='' onClick= {() => this.props.handleDeleteTodo(this.props.todos[index])}/>
            </div>
          );
          //Push done Todo in Done Array
          todoList[2].push(todoDone); 
        }
      });
      
      return todoList;
    }
  }

This is my SecondComponent for Inputs

import React from "react";
import { FormButton } from "./FormButton";

export class InputBar extends React.Component {
    render() {
      return (
        <form>
          <input
            type='text'
            placeholder="Type in a Note"
            value={this.props.enterTodo}
            onChange={this.props.handleEnterTodo}
            maxLength={20}
          />
          <FormButton lable= 'Enter' disabled={this.props.enterTodo == ''} onClick={this.props.handleCreateTodo}/>
          <FormButton lable= 'Clear' onClick={this.props.handleClearTodos}/>
        </form>
      );
    }
  }

My last Component for Buttons

import React from "react";

export class FormButton extends React.Component {
    render () {
        return (
            <button type='button' disabled={this.props.disabled} onClick={this.props.onClick}>
                {this.props.lable}
            </button>
        );
    }
}

Upvotes: 0

Views: 30

Answers (1)

Guillaume Brunerie
Guillaume Brunerie

Reputation: 5371

todoList is an array of elements, therefore this is the elements that should have a key, so you should add keys to the <div className="openTodos"> and <div className="doneTodos">.

Upvotes: 1

Related Questions