0
votes

I am getting this warning after already adding the key prop to the li items in TodoItems:

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of TodoItems

I have the following page:

<!DOCTYPE html>
<html>

<head>
    <title>todo-list</title>
    <script src="https://unpkg.com/[email protected]/dist/react.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/react-dom.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/4.0.0-beta.3/react-router.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/fixed-data-table/0.6.3/fixed-data-table.min.js"></script>
    <link href="https://cdnjs.cloudflare.com/ajax/libs/fixed-data-table/0.6.3/fixed-data-table.min.css" rel="stylesheet">

    <head>


        <body>
            <div style="margin-bottom: 35px">
                <a class="nav-link" href="/clock">clock</a>
                <a class="nav-link" href="/counter">counter</a>
                <a class="nav-link" href="/data-table-basic">data-table-basic</a>
                <a class="nav-link" href="/query-params-react-router">query-params-react-router</a>
                <a class="nav-link" href="/todo-list">todo-list</a>
                <a class="nav-link" href="/validated-form">validated-form</a>
            </div>


            <p>
                <a href="https://www.kirupa.com/react/simple_todo_app_react.htm" target="_blank">The tutorial link</a>
            </p>

            <div id="entry"></div>


            <script>
                function determineMode(filepath) {
                    var modeString = "ace/mode/" + filepath;
                    return modeString;
                }
            </script>

            <script src="/static/ace-builds2/src-noconflict/ace.js" type="text/javascript" charset="utf-8"></script>

            <script>
                var editor = ace.edit("editor");
                editor.getSession().setMode(determineMode('html'));
                editor.session.setNewLineMode("unix");
                editor.setTheme("ace/theme/monokai");
                editor.setFontSize(15);
            </script>

            <script type="text/babel">
                var destination = document.querySelector("#entry"); var TodoItems = React.createClass({ createTasks: function(item){ return this.props.entries.map(item => { return (
                <li data-bind-thisthing={item.key} key={item.key}>
                    <span>{item.text + " "} </span>
                    <a href="#" data-id="{item.id}" className="remove-filter" onClick={()=> this.props.remove(item)}
                        >
                            remove
                        </a>
                </li>
                ) }); }, render: function(){ return (
                <ul className="theList">
                    {this.createTasks()}
                </ul>
                ); } }); var TodoList = React.createClass({ getInitialState: function(){ return { items: [ 'If user clicks add button and input is empty, set a red border and focus the input box', 'Allow interactive DOM update of component when user edits code box', 'Allow categories for things like angular2, knockout, etc', 'Allow user to save new code snippets after starting in a sandbox', ] }; }, addItem: function(e) { var itemArray = this.state.items; if (this._inputElement.value.length > 0){ itemArray.push( { text: this._inputElement.value, key: this.state.items.length } ); this._inputElement.value = ""; this.setState({ items: itemArray }) } e.preventDefault(); }, // removing items from a list // http://stackoverflow.com/questions/27817241/how-to-remove-an-item-from-a-list-with-a-click-event-in-reactjs removeItem: function(item){ var items = this.state.items.filter(function(itm){ return item.key !== itm.key; }); this.setState({ items: items }); }, render: function() { return (
                <div className="todoListMain">
                    <div className="header">
                        <form onSubmit={this.addItem}>
                            <input ref={(a)=> this._inputElement = a} placeholder="enter task" />
                            <button type="submit">add</button>
                        </form>
                    </div>
                    <TodoItems remove={this.removeItem} entries={this.state.items} />
                </div>
                ); } }); ReactDOM.render(
                <div>
                    <TodoList/>
                </div>, destination );

            </script>
        </body>

</html>

enter image description here

Weird issues normally seem like this scope problems.

1
Initially items contains strings. They have neither text nor key property. That is why you see warning about duplicate keys and "undefined" as the output. BTW since user can remove elements you can't use array length at the time you add item as unique key.Yury Tarabanko
Not sure but I guess keys are used by react to query virtual dom. So elements are added by loops, you are binding same structure multiple times. Hence you need add key so react can differentiate between themRajesh
Check the key is duplicated.modernator

1 Answers

2
votes

Problem is initial state of TodoList. createTasks function is expecting entries (props) an array containing objects where each object should have keys id, text and key but its getting array containing strings.