CR Sardar
CR Sardar

Reputation: 1026

Each child in a list should have a unique "key"

New to react, can not understand why it is giving - Each child in a list should have a unique "key", Though I have added key? And line-through is not working.

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

        <script src="react.16.8.6.development.js"></script>
        <script src="react-dom.16.8.6.development.js"></script>
        <script src="babel.7.5.4.min.js"></script>
    </head>

    <body>
        <br>
        <div id="container"></div>

        <script type="text/babel">
            class ListItem extends React.Component{
                constructor(props){
                    super(props)
                    this.state = {isDone : false}
                }

                handleClick(){
                    var currentState = !this.state.isDone
                    this.setState({isDone : currentState})
                    console.log("handleClick : currentState = " + currentState)
                }

                render(){
                    var lineStyle = this.state.isDone ? "line-through" : "normal"
                    console.log("render : lineStyle = " + lineStyle + " : this.props.text = " + this.props.text)
                    return(
                        <li key={this.props.id.toString()}
                        onClick={this.handleClick.bind(this)} 
                        style = {{textDecoratipn:lineStyle}}>{this.props.text}
                        </li>
                    );
                }
            }

            class DynamicList extends React.Component{
                render(){
                    return(
                        <ul>
                        {this.props.listItems.map(function(item) {
                            return (<ListItem id={item.id} text={item.text}/>)
                            })
                        }
                        </ul>
                    )
                }
            }

            class MyApp extends React.Component{
                constructor(props){
                    super(props)
                    this.state = {id : 0, listItems : []}
                }
                onAdd(){
                    // e.preventDefault()
                    var textValue = document.getElementById("newItem").value

                    console.log("onAdd : textValue = " + textValue)

                    if(textValue){
                        var newItem =  {id : this.state.id, text : textValue}
                        var newListItems = this.state.listItems;
                        newListItems = newListItems.concat(newItem);

                        this.setState({id : (this.state.id + 1), listItems : newListItems})
                    }
                }

                render(){
                    return(
                        <div>
                        <input id="newItem" placeholder="New Item"></input>
                        <button onClick={this.onAdd.bind(this)}>Add</button>
                        <br/>
                        <DynamicList listItems={this.state.listItems}/>
                        </div>
                    )
                }
            }

            ReactDOM.render(
                <MyApp/>,
                document.getElementById("container")
            )

        </script>
    </body>
</html>

Upvotes: 2

Views: 215

Answers (2)

khan
khan

Reputation: 1464

When you're using .map() to render a list of elements, you need to include a key attribute:

class DynamicList extends React.Component {
    render() {
        return (
            <ul>
            {this.props.listItems.map(function(item) {
                // Include the key in ListItem
                return (<ListItem id={item.id} key={item.id} text={item.text}/>)
            })}
            </ul>
        )
    }
}

As for line-through not working, you misspelled textDecoration:

<li key={this.props.id.toString()}
    onClick={this.handleClick.bind(this)} 
    style = {{ textDecoration:lineStyle }}> 
    {this.props.text}
</li>

Upvotes: 4

ravibagul91
ravibagul91

Reputation: 20765

A key is a special string attribute you need to include when creating lists of elements.

From the docs,

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity:

So your need to add key here,

{this.props.listItems.map(function(item) {
  return (<ListItem id={item.id} key={item.id} text={item.text}/>) //key added here
  })
}

Upvotes: 1

Related Questions