【问题标题】:array.splice(index, 1) returns array with removed itemarray.splice(index, 1) 返回删除项目的数组
【发布时间】:2020-11-30 15:13:32
【问题描述】:

我正在学习反应钩子,我只是想做一个简单的功能来从列表中删除项目。为此,我使用了 find、indexOf 和 splice。

在 onClick 函数中,我在 array.splice(indexOf, 1) 中使用 indexOf,但它只返回列表中的项目。一切都会重新渲染并执行它应该做的事情,但唯一渲染的项目是我刚刚尝试删除的项目。我错过了什么?

const [todos, setToDo] = useState(initialToDo);
const [input, setInput] = useState('');

const todoList = (todos) => {
    return (
        todos.map((todo) => {
        return (
            <div className='todo-list flex p-2 w-1/2 justify-between'>
                <p className="px-3">{todo.name}</p>
                <button 
                    className='rounded-sm border-2 px-2'
                    onClick={(e)=>{
                        let item = todos.find(el=>el.id == todo.id);
                        console.log(item)
                        let index = todos.indexOf(item);
                        console.log(index)
                        todos = todos.splice(index, 1)
                        // todos == item
                        setToDo(todos)
                    }}    
                >-</button>
            </div>
    )}))
}

【问题讨论】:

  • splice 返回被删除的元素 - 不是更新后的数组
  • splice 为您提供了您“拼接”出来的元素 splice 的作用正好相反
  • 你可以使用Array.prototype.filter(),虽然它的拼接有点复杂。此外,splice 修改了原始数组,所以不要将 todos 重新分配为 splice 的返回值,让它成为自己的一行。
  • @Samathingamajig 更复杂吗?它完全完成一项工作,并且每次都完全相同。 Splice 至少有三种不同的效果,你可以使用它,如果不是更多的话。您使用的语法会因您需要的语法而大不相同。即使你正确地调用.splice(),你仍然可以在这个网站上显示关于.splice() 的许多问题。一个非常常见的问题是在前向循环中使用.splice()。我不太确定您为什么认为这“更简单”或“更容易”。

标签: javascript arrays reactjs react-hooks


【解决方案1】:

是的,Array.splice 返回删除的元素并改变原始数组,这意味着您可以使用index 删除/更新todos 列表中的待办事项。

执行此操作的最简单方法是以下方法。这是working example

const todoList = () => {
  const [todos, setToDo] = useState(initialToDo);
  const [input, setInput] = useState('');

  const handleDelete = index => {
    todos.splice(index, 1)
    setToDo([...todos])
  }

  return (
    todos.map((todo, index) => {
    return (
      <div className='todo-list flex p-2 w-1/2 justify-between'>
        <p className="px-3">{todo.name}</p>
        <button 
          className='rounded-sm border-2 px-2'
          onClick={() => handleDelete(index)}    
        >
        -
       </button>
      </div>
  )}))
}

【讨论】:

    【解决方案2】:

    splice 返回已删除的项目。我建议改用filter,例如:

    setToDo(todos.filter(({ id }) => id != todo.id));
    

    【讨论】:

      【解决方案3】:

      使用filter 而不是使用splice 进行变异。试试这个 sn-p。

      const TodoList = () => {
        const [todos, setTodos] = React.useState([
          { name: 'a', id: 1 },
          { name: 'b', id: 2 },
        ]);
        return todos.map((todo) => {
          return (
            <div>
              <p>{todo.name}</p>
              <button onClick={() => setTodos(todos.filter(item => item.id !== todo.id))} > - </button>
            </div>
          );
        });
      };
      
      const domContainer = document.querySelector('#app');
      ReactDOM.render(<TodoList />, domContainer);
      <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
      <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
      
      <div id="app"> </div>

      【讨论】:

        猜你喜欢
        • 2021-01-19
        • 2016-12-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-30
        • 2018-06-02
        • 2022-09-27
        • 2011-06-01
        相关资源
        最近更新 更多