如何防止React重新渲染?

时间:2020-03-21 06:28:42

标签: javascript reactjs

我正在学习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>
    );
  }
}

5 个答案:

答案 0 :(得分:1)

您可以在注释中看到模板中有一个表单。如果单击按钮,则模板中的表单将被提交,这将导致回发,即页面重新加载。因此,要么停止提交 (1) 形式,要么将按钮的类型更改为type="button"

<button type="button"

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


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

答案 1 :(得分:1)

如果要避免在发生提交事件时刷新页面,则应使用preventDefault()

如果您想在React中禁用整个页面的呈现,而仅重新呈现页面的某些部分,则可以使用两种解决方案:

  1. prevProps内的prevStatecomponentDidUpdate进行类组件的额外比较:

    componentDidUpdate(prevProps, prevState) { if(prevState.taskList !== this.state.taskList) { // do your magic here } }

  2. useEffect()钩在功能组件中:

如果在重新渲染之间某些值未更改,您可以告诉React跳过应用效果。为此,请将数组作为可选的第二个参数传递给useEffect:

useEffect(() => {
    // do your magic here
}, [taskList]); // Only re-run the effect if taskList changes

您可以在official React documentation中找到有关此功能的更多信息。

答案 2 :(得分:0)

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

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

答案 3 :(得分: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对象。然后传递项目以外的索引。

答案 4 :(得分:0)

1。您正在使用html的form元素。并且由于您正在使用其中的按钮,因此您需要添加e.preventDefault,否则它将像提交并刷新页面一样。

2。在handleDelete中传递参数时,您既未传递event,也未传递index。要使用splice,您需要元素的index

3。作为回应,我建议使用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都会始终重新渲染该组件。在这里,删除时任务列表状态正在更改。因此组件正在重新渲染。