如何防止React重新渲染?

4

我正在学习React,并且目前正在尝试创建一个待办事项列表。一切都运作良好,但是当我尝试从数组中删除一个项目时,整个页面都会重新渲染。

请问有人可以告诉我我错在哪里吗?我只想在点击按钮后删除特定的项目,而不重新渲染整个页面。

代码:

import React, { Component } from "react";
import "./todo.css";

class Todo extends Component {
  constructor(props) {
    super(props);
    this.state = {
      task: "",
      taskList: []
    };
  }

  handleAdd = e => {
    e.preventDefault();
    this.setState({
      task: "",
      taskList: [...this.state.taskList, this.state.task]
    });
  };

  onChange = e => {
    this.setState({
      task: e.target.value
    });
  };

  handleDelete = task => {
    console.log(task);
    const newtaskList = this.state.taskList.splice(task, 1);
    this.setState({
      taskList: newtaskList
    });
    console.log(task);
  };

  render() {
    return (
      <form className='App'>
        <div className='input input-group mb-3'>
          <input
            type='text'
            className='form-control'
            placeholder='Enter a task'
            value={this.state.task}
            onChange={this.onChange}
          />
          <button className='btn btn-primary' onClick={this.handleAdd}>
            ADD
          </button>
        </div>
        <div className='output' id='output'>
          <ul className='list-group'>
            {this.state.taskList.map((task, index) => (
              <li
                className='list-group-item'
                key={index}
                style={{
                  display: "flex",
                  justifyContent: "space-between",
                  alignContent: "center"
                }}>
                {task}
                <div className='input-group-prepend'>
                  <button
                    className='btn btn-danger'
                    onClick={() => this.handleDelete(task)}>
                    Done
                  </button>
                </div>
              </li>
            ))}
          </ul>
        </div>
      </form>
    );
  }
}

3
请在 handleDelete 函数中添加 e.preventDefault();。这样可以防止默认行为的发生。 - Utsav Patel
将此代码 onClick={() => this.handledelete(task)} 替换为 onClick={(e) => this.handledelete(e, task)} - Sajeeb Ahamed
重新渲染是一项很好的功能,可以在状态对象更新时保持应用程序的更新。您试图解决什么问题? - Jai
2
不是React的重新渲染,而是表单提交导致页面刷新。 - Agney
只需在删除按钮中添加 type,例如 <button type="button" 即可解决问题。 - palaѕн
5个回答

1
正如您在评论中所见,您的模板中有一个表单。如果您点击按钮,则会提交模板中的表单,这将导致页面重新加载。因此,您要么停止表单提交(1),要么将按钮类型更改为type="button"
<button type="button"

默认行为是type="submit",所以更改类型将解决您的问题。

1. 您没有任何表单提交事件。


1
如果您想在提交事件发生时避免刷新页面,则应使用preventDefault()。
如果您想禁用React中的整个页面渲染,并仅重新渲染页面的某些部分,可以使用两种解决方案:
1. 对于类组件,请在componentDidUpdate中使用prevProps或prevState进行额外比较: componentDidUpdate(prevProps, prevState) { if(prevState.taskList !== this.state.taskList) { // 在此处执行操作 } }
2. 对于函数式组件,请使用useEffect() hook: 您可以告诉React在重新渲染时跳过应用某些值未更改的effect。为此,请将数组作为useEffect的可选第二个参数传递:
useEffect(() => {
    // do your magic here
}, [taskList]); // Only re-run the effect if taskList changes

您可以在React官方文档中找到更多关于这种功能的信息。


0

这是由于您的 React 组件中表单提交引起的,如评论中所述,您应该使用 e.preventDefault() 来防止按钮提交的默认行为:

...
<button
  className='btn btn-danger'
  onClick={(e) => {
    e.preventDefault(); 
    this.handleDelete(task)
  }}>
  Done
</button>
...

0

Splice(切片)通过索引删除元素并返回已删除的元素,它在切片后操作原始数组。

您需要做的是更改handleDelete函数。事件函数的第一个参数是事件对象。因此,请将其作为第一个参数传递并绑定任何其他参数。

您可以尝试这个-

handleDelete = (e, index) => {
    console.log(index);
    e.preventDefault();
    const copyTask = [...this.state.taskList];
    copyTask.splice(index, 1); // Splice directly change the copyTask array.

    this.setState({
      taskList: copyTask
    });
  };

同时也更改这一行 -

onClick={(e) => this.handleDelete(e, index)}

第一个参数是event对象。然后传递除该项之外的索引。


0

1.你正在使用HTML的form元素。由于你在其中使用了按钮,所以需要添加e.preventDefault,否则它会像提交并刷新页面一样。

2.在传递参数到handleDelete时,你既没有传递event也没有传递index。要使用splice,你需要该元素的index

3.在React中,我建议使用spread operator来避免改变状态。

因此,请替换这两个内容。

handleDelete = (e , index) => {
    e.preventDefault();
    const { taskList } = this.state;
    this.setState({
      taskList: [...taskList.slice(0 , index) , ...taskList.slice(index + 1)]
    });
  };

并且,在调用处理删除功能的时候使用,

onClick={(e) => this.handleDelete(e, index)}

关于重新渲染。如果组件中的任何状态发生更改,React将始终重新渲染该组件。在这里,当您删除时,tasklist状态正在发生更改。因此,组件正在重新渲染。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接