首页 > 解决方案 > 状态更新时反应页面不重新渲染

问题描述

我已经使用反应钩子实现了一个 todolist 应用程序。我这里有两个状态。一个是保存文本字段值的名称状态。还有一个是 List 状态,它将待办事项列表的内容保存为一个数组。

现在当我添加项目时,我更新列表状态并且页面重新呈现正常。但是当我删除一个选定的项目时,我会更新 List 数组,它会在我检查日志时更新,它会再次重新渲染..但我在 UI 上看不到变化。所以简而言之,删除一个项目处理程序在我的代码中不起作用。

import React,{useState} from "react"
import {render} from "react-dom"

const  App = ()=> {

    const [taskList, setTaskList] = useState([])
    const [taskField, setTaskField] = useState("");

    function handleTaskFieldChange(e){
        setTaskField(e.target.value);
    }

    function handleAddClick(){
        if(taskField){
             setTaskList([...taskList, taskField])
             setTaskField("")
        }
    }

    function removeButtonHandler(e){
        var i = e.target.id;
        var list = taskList;
        list.splice(i,1)
        console.log(list)
        setTaskList(list)
    }

    return(
        <div>
            <div>
               <b> TO DO LIST</b>
            </div>
            <div 
            className= "inputAdd">
                <input
                value={taskField}
                placeholder="enter new task "
                onChange = {handleTaskFieldChange} >
                </input>
                <button                
                onClick = {handleAddClick}
                >
                    Add +
                </button>
            </div>
            {
            taskList.map((element,index) =>  {
                console.log("repaint list", taskList)
                return(
                <div
                className="listItem"
                key={index}>
                <span>{index + 1}. {element}</span>
                <button
                key={index}
                id={index}
                onClick={removeButtonHandler}
                >
                    remove
                </button>
            </div>)

                })
            }
        </div>
    )
}

render(<App/>, document.getElementById("root"))

你们能告诉我我的删除按钮处理程序有什么问题吗?为什么在删除项目后它不呈现更新的列表。?

标签: reactjs

解决方案


尽量避免使用.splice(). 为了让 React 正确渲染更新后的状态,您需要传入一个全新的状态对象。

触发后removeButtonHandler,我们可以使用.filter()创建一个新的项目列表,不包括您选择要删除的项目。然后将该新列表传递给setTaskList()

工作沙箱:https ://codesandbox.io/s/dawn-frog-gv79h

import React, { useState } from "react";
import ReactDOM from "react-dom";

const App = () => {
  const [taskList, setTaskList] = useState([]);
  const [taskField, setTaskField] = useState("");

  function handleTaskFieldChange(e) {
    setTaskField(e.target.value);
  }

  function handleAddClick() {
    if (taskField) {
      setTaskList([...taskList, taskField]);
      setTaskField("");
    }
  }

  function removeButtonHandler(e) {
    var i = e.target.id;
    const updatedTasks = taskList.filter(
      (field, fieldIndex) => fieldIndex != i
    );
    setTaskList(updatedTasks);
  }

  return (
    <div>
      <div>
        <b> TO DO LIST</b>
      </div>
      <div className="inputAdd">
        <input
          value={taskField}
          placeholder="enter new task "
          onChange={handleTaskFieldChange}
        />
        <button onClick={handleAddClick}>Add +</button>
      </div>
      {taskList.map((element, index) => {
        return (
          <div className="listItem" key={index}>
            <span>
              {index + 1}. {element}
            </span>
            <button key={index} id={index} onClick={removeButtonHandler}>
              remove
            </button>
          </div>
        );
      })}
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

推荐阅读