如何删除React中的待办事项项?

时间:2017-06-29 17:52:08

标签: reactjs

我正在使用React做一个简单的todo应用程序,只是为了练习。点击它后如何删除列表项?

这是我的todos.js

export default class Todos extends Component {
    constructor(props) {
        super(props);
        this.state = { todos: [], text: '' };
    }

    addTodo(e) {
        e.preventDefault();
        this.setState({ todos: [ this.state.text, ...this.state.todos ] });
        this.setState({ text: ''});
    }

    updateValue(e) {
        this.setState({ text: [e.target.value]})
    }

    render() {
        return(
            <div>
                <form onSubmit = {(e) => this.addTodo(e)}>
                    <input
                        placeholder="Add Todo"
                        value={this.state.text}
                        onChange={(e) => {this.updateValue(e)}}
                    />
                    <button type="submit">Add Todo</button>
                </form>
                <TodoList todos={this.state.todos}/>
            </div>
        );
    }
}

这是TodoList.js,我试图从中删除列表项。

import React, { Component } from 'react';
import { connect } from 'react-redux';

export default class TodoList extends Component {
    removeItem(e) {
        // splice this.props.todos??
    }
    render() {
        return(
            <ul>
                { this.props.todos.map((todo) => {
                    return <li onClick={(e) => { this.removeItem(e)}} key={todo}>{ todo }</li>
                })}
            </ul>
        );
    }
}

7 个答案:

答案 0 :(得分:11)

要删除待办事项,请先从父组件传递一个函数:

<TodoList todos={this.state.todos} removeTodo={this.removeTodo}/>

将此功能绑定在constructor

this.removeTodo = this.removeTodo.bind(this);

在父组件中定义此函数,它将从state变量:

中删除该项
removeTodo(name){
    this.setState({
        todo: this.state.todo.filter(el => el !== name)
    })
}

然后在子组件内部调用此方法来删除todo:

export default class TodoList extends Component {
    removeItem(e) {
        this.props.removeTodo(item);
    }
    render() {
        return(
            <ul>
                { this.props.todos.map((todo) => {
                    return <li onClick={() => { this.removeItem(todo)}} key={todo}>{ todo }</li>
                })}
            </ul>
        );
    }
}

<强>建议:

如果您想设置多个setState值,请不要在function内多次调用state,然后将其写为:

this.setState({
    a: value1,
    b: value2,
    c: value3
})

工作示例:

class Todos extends React.Component {
    constructor(props) {
        super(props);
        this.state = { todos: [], text: '' };
        this.removeTodo = this.removeTodo.bind(this);
    }

    addTodo(e) {
        e.preventDefault();
        this.setState({ 
        	todos: [ this.state.text, ...this.state.todos ],
        	text: ''
        });
    }

    removeTodo(name, i){
        let todos = this.state.todos.slice();
        todos.splice(i, 1);
        this.setState({
            todos
        });
    }

    updateValue(e) {
        this.setState({ text: e.target.value})
    }

    render() {
        return(
            <div>
                <form onSubmit = {(e) => this.addTodo(e)}>
                    <input
                        placeholder="Add Todo"
                        value={this.state.text}
                        onChange={(e) => {this.updateValue(e)}}
                    />
                    <button type="submit">Add Todo</button>
                </form>
                <TodoList todos={this.state.todos} removeTodo={this.removeTodo}/>
            </div>
        );
    }
}

class TodoList extends React.Component {

    removeItem(item, i) {
        this.props.removeTodo(item, i);
    }

    render() {
        return(
            <ul>
                { this.props.todos.map((todo,i) => {
                    return <li onClick={() => { this.removeItem(todo, i)}} key={i}>{ todo }</li>
                })}
            </ul>
        );
    }
}

ReactDOM.render(<Todos/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'/>

<强>更新

这对于@ whs.bsmith有疑问,我建议的代码将在用户将在待办事项列表中添加唯一项目的情况下正常工作,如果他将尝试添加它将不会在ui中反映的相同项目因为OP使用todo项目名称作为密钥,密钥应该是唯一的。

要解决这个问题:

在工作片段中,我使用索引代替todo项目名称为密钥,这将正常工作,它将允许用户多次添加相同的项目,并在删除时,它将只删除该特定项目而不是所有项目同名,但使用索引作为关键并不是一个好主意。

答案 1 :(得分:2)

您已在 addTodo 函数中调用 setState 两次。您可以在单个setState函数中设置 todos text ,如下所示:

addTodo(e) {
    e.preventDefault();
    this.setState({ todos: [ this.state.text, ...this.state.todos ], text: '' });
}

不要在 TodoList 组件中编写 removeItem 函数,因为它纯粹是在使用道具。将删除项函数从 Todos 传递给它并在Todos的removeItem函数中删除该项,如下所示:

import React, {Component} from 'react'
export default class Todos extends Component {
  constructor(props) {
    super(props);
    this.state = { todos: [], text: '' };
    this.removeItem = this.removeItem.bind(this)
  }

  addTodo(e) {
    e.preventDefault();
    this.setState({ todos: [ this.state.text, ...this.state.todos ], text: '' });
  }


  updateValue(e) {
    this.setState({ text: [e.target.value]})
  }
  removeItem(index) {
    const todos = this.state.todos.filter((todo, todoIndex) => {
      return todoIndex !== index
    })
    this.setState({ todos })
  }
  render() {
    return(
      <div>
        <form onSubmit = {(e) => this.addTodo(e)}>
          <input
            placeholder="Add Todo"
            value={this.state.text}
            onChange={(e) => {this.updateValue(e)}}
            />
          <button type="submit">Add Todo</button>
        </form>
        <TodoList todos={this.state.todos} removeItem={this.removeItem} />
      </div>
    );
  }
}

class TodoList extends Component {
  render() {
    return(
      <ul>
        { this.props.todos.map((todo, index) => {
          return <li onClick={(e) => { this.props.removeItem(index)}} key={todo}>{ todo }</li>
        })}
      </ul>
    );
  }
}

希望,这有帮助。

答案 2 :(得分:0)

唯一要做的就是将companion object { @JvmStatic fun main(args: Array<String>) { A().i = B.I {} } } 移至todos中的state,并将当前待办事项的索引传递给TodoList方法。然后按照你的建议拼接它。

removeItem

TodoList

删除项目Removing element from array in component state

答案 3 :(得分:0)

首先,您希望removeItem方法存在于Todos类中,因为那就是它 状态存储。然后,您可以使用过滤器或切片

export default class Todos extends Component {
    constructor(props) {
        super(props);
        this.state = { todos: [], text: '' };
    }

    addTodo(e) {
        e.preventDefault();
        this.setState({ todos: [ this.state.text, ...this.state.todos ] });
        this.setState({ text: ''});
    }

    updateValue(e) {
        this.setState({ text: [e.target.value]})
    }

    removeItem = index => {
        //either use filter
        const { todos } = this.state;
        const newTodos = todos.filter((todo, i) => i !== index);
        this.setState({ todos: newTodos});

        //or use slice
        const slicedNewTodos = todos.slice(0, index).concat(todos.slice(index + 1));
        this.setState({ todos: slicedNewTodos});
    }

    render() {
        return(
            <div>
                <form onSubmit = {(e) => this.addTodo(e)}>
                    <input
                        placeholder="Add Todo"
                        value={this.state.text}
                        onChange={(e) => {this.updateValue(e)}}
                    />
                    <button type="submit">Add Todo</button>
                </form>
                <TodoList removeItem={this.removeItem} todos={this.state.todos}/>
            </div>
        );
    }
}

import React, { Component } from 'react';
import { connect } from 'react-redux';

class TodoList extends Component {
    render() {
        return(
            <ul>
                { this.props.todos.map((todo, index) => {
                    return <li onClick={() => this.props.removeItem(index)} key={todo}>{ todo }</li>
                })}
            </ul>
        );
    }
}

答案 4 :(得分:0)

class TodoList extend React.Component{
    constructor(props){
        super(props);
        this.state = {
            todos: [],
            todo: ''
        }
        this.changeTodo = this.changeTodo.bind(this);
        this.addTodo = this.addTodo.bind(this);
        this.removeTodo = this.removeTodo.bind(this);
    }

    changeTodo(event){
        this.setState({
            todo: event.target.value
        })
    }

    addTodo(){
        let { todo, todos } = this.state;
        this.setState({
            todo: '',
            todos: [...todos, todo]
        })
    }

    removeTodo(index){
        let { todos } = this.state;
        todos.splice(index, 1);
        this.setState({
            todos: todos
        })
    }

    render(){
        let { todo, todos } = this.state;
        return <div>
            <input value={todo} onChange={this.changeTodo}/>
            <button onClick={this.addTodo}>Add Todo</button>
            {
                todos.map((todo, index)=>{
                    return <h1 onClick={this.removeTodo.bind(undefined, index)} key={index}>{todo}</h1>
                })
            }
        </div>
    }
}

这是TodoList的一个小例子。浏览此代码以了解删除TodoList应用中的待办事项。

答案 5 :(得分:0)

每个人都给出了很好的概览。 我发现这是从待办事项列表中删除待办事项的好方法

  

todolist.splice(index,1);

Splice从索引的startIndex中删除1个元素(在todolist数组中)

答案 6 :(得分:0)

我们可以为待办事项数据设置一个标志,在初始化该数据时,我们可以将标志设置为 true,当我们删除待办事项列表时,我们可以将标志设置为 false。请参考以下代码。

const TodoComponent = ({ dataArray }) => {

  const [todos, setTodos] = useState(dataArray)

  // initial loading of todo items.
  useEffect(() =>{
    if (dataArray.length) {
      dataArray.forEach(todo =>{
        todo.show = true
      })
      setTodos(dataArray)
    }
  }, [dataArray])

 // Close the todo Item.
  const closeTodoItem = (todo, index) =>{
    todo.show = false
    todos[index] = todo
    setTodos([...todos])
  }

  return (
    todos.filter(todo => todo.show === true).length >0  &&
    (
      <Col span={24} className={style.todoBg} style={compStyle}>
        {todos.map((todo,index) => (
          (todo.show && (
            <Col span={24} className={style.todo}>
              <Col className={style.todoInner}>
                <p> {todo.content} </p>
              </Col>
              <Icon onClick={() => closeTodoItem(todo, index)} className={style.close}>close</Icon>
            </Col>
          ))
        ))}
      </Col>
    )
  )}

上述方法对我有用。