admin管理员组

文章数量:1406308

I've been working on understanding React concepts and did my Todo project. I have the dummy data displaying, but can't add a new value to my dummy data, which is stored in an array of objects in a separate file, todos.js.

Here is the file hierarchy


Here is the error I am getting -

index.js:2177 Warning: Each child in an array or iterator should have a unique "key" prop.


TodoList.js

import React from 'react';
import Todo from './Todo';
import todos from '../todos'

class TodoList extends React.Component {
    constructor() {
        super();
        this.state = {
            todoItems: todos,
            newItem: {}
        }
    }

    addItem = (event) => {
        event.preventDefault();
        const todoList = this.state.todoItems;
        todoList.push(this.state.newItem);
        this.setState({ 
            todoList: todos,
            newItem: {}
        });

    };

    handleInput = (event) => {
        this.setState({ newItem: event.target.value });
    }

    render() {
        const itenary = this.state.todoItems;
        return (
            <div>
                {itenary.map(todo =>
                    <div key={todo.id}>
                        <Todo handleClick={this.props.handleClick} thing={todo} />
                    </div>

                )}
                <br />
                <form onSubmit={this.addItem}>
                    <input type="text" onChange={this.handleInput} placeholder="Add a new task" />
                    <button>Submit</button>
                </form>
            </div>
        );
    }
}

export default TodoList;

Todo.js

import React from 'react';

class Todo extends React.Component {
    constructor() {
        super();
        this.state = {
            clicked: false
        }
    }


    handleClick = () => {
        this.setState({ clicked: !this.state.clicked });
    }

    render() {
        const styles = this.state.clicked ? { textDecoration: 'line-through' } : { textDecoration: 'none' };
        return (
            {/* This is where the todo item is*/}
            <div style={styles} onClick={this.handleClick} key={this.props.thing.id}>{this.props.thing.text}</div>
        );
    }
}

export default Todo;

todos.js

const todos = [
    { id: 1, text: 'Go to the gym', 'pleted': false },
    { id: 2, text:  'Do laundry', 'pleted': false },
    { id: 3, text: 'Study for exams', 'pleted': false },
    { id: 4, text: 'Read a book', 'pleted': false },
    { id: 5, text: 'Clean the bedroom', 'pleted': false },
    { id: 6, text: 'Go to the park', 'pleted': false },
];

export default todos; 

Any help and/or feedback is appreciated.

I've been working on understanding React concepts and did my Todo project. I have the dummy data displaying, but can't add a new value to my dummy data, which is stored in an array of objects in a separate file, todos.js.

Here is the file hierarchy


Here is the error I am getting -

index.js:2177 Warning: Each child in an array or iterator should have a unique "key" prop.


TodoList.js

import React from 'react';
import Todo from './Todo';
import todos from '../todos'

class TodoList extends React.Component {
    constructor() {
        super();
        this.state = {
            todoItems: todos,
            newItem: {}
        }
    }

    addItem = (event) => {
        event.preventDefault();
        const todoList = this.state.todoItems;
        todoList.push(this.state.newItem);
        this.setState({ 
            todoList: todos,
            newItem: {}
        });

    };

    handleInput = (event) => {
        this.setState({ newItem: event.target.value });
    }

    render() {
        const itenary = this.state.todoItems;
        return (
            <div>
                {itenary.map(todo =>
                    <div key={todo.id}>
                        <Todo handleClick={this.props.handleClick} thing={todo} />
                    </div>

                )}
                <br />
                <form onSubmit={this.addItem}>
                    <input type="text" onChange={this.handleInput} placeholder="Add a new task" />
                    <button>Submit</button>
                </form>
            </div>
        );
    }
}

export default TodoList;

Todo.js

import React from 'react';

class Todo extends React.Component {
    constructor() {
        super();
        this.state = {
            clicked: false
        }
    }


    handleClick = () => {
        this.setState({ clicked: !this.state.clicked });
    }

    render() {
        const styles = this.state.clicked ? { textDecoration: 'line-through' } : { textDecoration: 'none' };
        return (
            {/* This is where the todo item is*/}
            <div style={styles} onClick={this.handleClick} key={this.props.thing.id}>{this.props.thing.text}</div>
        );
    }
}

export default Todo;

todos.js

const todos = [
    { id: 1, text: 'Go to the gym', 'pleted': false },
    { id: 2, text:  'Do laundry', 'pleted': false },
    { id: 3, text: 'Study for exams', 'pleted': false },
    { id: 4, text: 'Read a book', 'pleted': false },
    { id: 5, text: 'Clean the bedroom', 'pleted': false },
    { id: 6, text: 'Go to the park', 'pleted': false },
];

export default todos; 

Any help and/or feedback is appreciated.

Share Improve this question asked Aug 6, 2018 at 0:29 dk7518dk7518 1552 gold badges2 silver badges9 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 2

You must give the new todo you add to todoItems a unique id that React can use to distinguish it from the others when you render them.

You should also not mutate the current state by using push. You should instead set state with an entirely new array that contains everything the previous one did.

Example

class TodoList extends React.Component {
  constructor() {
    super();
    this.state = {
      todoItems: todos,
      newItem: ""
    };
  }

  addItem = event => {
    event.preventDefault();
    this.setState(prevState => {
      return {
        todoItems: [
          ...prevState.todoItems,
          { id: Math.random(), text: prevState.newItem, pleted: false }
        ],
        newItem: ""
      };
    });
  };

  // ...
}

const todos = [
  { id: 1, text: "Go to the gym", pleted: false },
  { id: 2, text: "Do laundry", pleted: false },
  { id: 3, text: "Study for exams", pleted: false },
  { id: 4, text: "Read a book", pleted: false },
  { id: 5, text: "Clean the bedroom", pleted: false },
  { id: 6, text: "Go to the park", pleted: false }
];

class TodoList extends React.Component {
  constructor() {
    super();
    this.state = {
      todoItems: todos,
      newItem: ""
    };
  }

  addItem = event => {
    event.preventDefault();
    this.setState(prevState => {
      return {
        todoItems: [
          ...prevState.todoItems,
          { id: Math.random(), text: prevState.newItem, pleted: false }
        ],
        newItem: ""
      };
    });
  };

  handleInput = event => {
    this.setState({ newItem: event.target.value });
  };

  render() {
    const itenary = this.state.todoItems;
    return (
      <div>
        {itenary.map(todo => (
          <div key={todo.id}>
            <Todo handleClick={this.props.handleClick} thing={todo} />
          </div>
        ))}
        <br />
        <form onSubmit={this.addItem}>
          <input
            type="text"
            onChange={this.handleInput}
            value={this.state.newItem}
            placeholder="Add a new task"
          />
          <button>Submit</button>
        </form>
      </div>
    );
  }
}

class Todo extends React.Component {
  constructor() {
    super();
    this.state = {
      clicked: false
    };
  }

  handleClick = () => {
    this.setState({ clicked: !this.state.clicked });
  };

  render() {
    const styles = this.state.clicked
      ? { textDecoration: "line-through" }
      : { textDecoration: "none" };
    return (
      <div style={styles} onClick={this.handleClick} key={this.props.thing.id}>
        {this.props.thing.text}
      </div>
    );
  }
}

ReactDOM.render(<TodoList />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>

You can always define the Object/s array within a function accepting an array: In this example:

const [programs, setPrograms] = useState([]);

In order to create a single JSON program array:

setPrograms([{id: program?.id, title: program?.title}]);

本文标签: javascriptHow do I add input data to JSON array in ReactStack Overflow