javascript - How to prevent React from re render? - Stack Overflow

I'm learning React and am currently trying to create a todo list. Everything works fine, however,

I'm learning React and am currently trying to create a todo list. Everything works fine, however, when I try to delete an item in the array, the whole page gets re-rendered.

Can someone please let me know where I went wrong? I just want to delete a specific item once the button is clicked and not re-render the whole page.

Code:

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>
    );
  }
}

I'm learning React and am currently trying to create a todo list. Everything works fine, however, when I try to delete an item in the array, the whole page gets re-rendered.

Can someone please let me know where I went wrong? I just want to delete a specific item once the button is clicked and not re-render the whole page.

Code:

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>
    );
  }
}
Share Improve this question edited Mar 21, 2020 at 10:10 user11422223 asked Mar 21, 2020 at 6:28 Dylan PhamDylan Pham 411 silver badge3 bronze badges 5
  • 3 Try adding e.preventDefault(); in the handleDelete function – Utsav Patel Commented Mar 21, 2020 at 6:30
  • Change this onClick={() => this.handledelete(task)} by onClick={(e) => this.handledelete(e, task)} – Sajeeb Ahamed Commented Mar 21, 2020 at 6:32
  • re-rendering is a good feature to keep the app updated as state object updates. What is the issue you are trying to solve? – Jai Commented Mar 21, 2020 at 6:32
  • 2 It's not the re-render from react, it's the form submit that is refreshing the page – Agney Commented Mar 21, 2020 at 6:39
  • Just add type to delete button like <button type="button" to fix the issue. – palaѕн Commented Mar 21, 2020 at 6:43
Add a ment  | 

5 Answers 5

Reset to default 1

As you can see in the ment you have a form in your template. If you click the button your form in the template get submitted which causes in a postback which is a page reload. So either you stop the submission of form(1) or change the type of the button to type="button":

<button type="button"

The default behavior is type="submit", so changing the type would resolve your issue.


1. You don't have any form submit event.

If you want to avoid refreshing page when submit event occure then you should use preventDefault().

If you want to disable whole page rendering in React and re-render only some parts of you page, you can use two solutions:

  1. extra parison with prevProps or prevState inside ponentDidUpdate for class ponent:

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

  2. useEffect() hook in functional ponent:

You can tell React to skip applying an effect if certain values haven’t changed between re-renders. To do so, pass an array as an optional second argument to useEffect:

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

More information about this kind of feature you can find in official React documentation.

This is caused by form submit in your react ponent as mentioned in the ments, you should use e.preventDefault() to prevent the default behavior for the button submit:

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

Splice removes an element by index and returns the removed element and it manipulates the original array after splicing.

What you need to do is to change the handleDelete function. First parameter of an event function is the event object. So pass it as the first parameter and bind any other params with it.

You can try this-

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
    });
  };

And also change this line-

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

First param is the event object. Then pass the index other than the item.

1.You are using form element of html. And since you are using button inside it you need to add e.preventDefault else it would act like submit and refresh the page.

2.While passing params in handleDelete you are not passing event neither you are passing index. To use splice you need the index of the element.

3.In react, I would suggest to use spread operator that helps not to mutate the state.

So, please replace these two things.

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

and, while calling handle delete function use,

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

And, regarding re-render. React will always re-render the ponent if any state in that ponent is getting changed. Here, tasklist state is getting changed when you are deleting. So ponent is getting re-rendered.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744726722a4590224.html

相关推荐

  • javascript - How to prevent React from re render? - Stack Overflow

    I'm learning React and am currently trying to create a todo list. Everything works fine, however,

    13小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信