You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS操作按钮失效、删除模态框不显示问题排查求助

问题排查与修复:React用户管理页面删除按钮失效及模态框问题

问题概述

用户管理页面可展示localStorage中的用户数据,但删除按钮点击无响应、模态框无法弹出;当前用户删除按钮已隐藏,但动态ID样式未生效,控制台抛出错误:

Uncaught ReferenceError: showDeleteModal1676598011384 is not defined
at HTMLButtonElement.onclick

错误原因

  • 原生DOM操作违背React范式:手动通过document.createElement和innerHTML生成DOM,React无法追踪这些元素的事件绑定,且拼接的showDeleteModal${user.id}会被当作全局函数调用,而组件内函数属于局部作用域,全局无法找到。
  • 事件绑定与动态ID语法错误:删除按钮的id={delete-${user.id}}语法错误,onClick属性未正确传递参数,不符合React事件绑定规范。
  • 状态更新逻辑错误:直接修改useState返回的数组(如users.splice),React无法感知状态变化,页面不会重渲染;showDeleteModal内部存在递归调用showDeleteModal(),会触发无限循环。
  • 模态框按钮逻辑错误:OK按钮被Link包裹会导致页面跳转,中断删除流程,且未传递目标用户ID。

修复后的完整代码

import Nav from "./Nav";
import { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import "./css/table.css";
import "./css/modal.css";
import "./css/user-list.css";

const ManageUsers = () => {
  // 将状态改为可更新的,便于触发重渲染
  const [users, setUsers] = useState(
    localStorage.getItem('users')
      ? JSON.parse(localStorage.getItem('users'))
      : []
  );
  const [loggedInData] = useState(
    localStorage.getItem('loggedIn')
      ? JSON.parse(localStorage.getItem('loggedIn'))
      : []
  );
  const [chats, setChats] = useState(
    localStorage.getItem('chats') ? JSON.parse(localStorage.getItem('chats')) : []
  );
  const [uploads, setUploads] = useState(
    localStorage.getItem('uploads')
      ? JSON.parse(localStorage.getItem('uploads'))
      : []
  );
  const [selectedDeleteId, setSelectedDeleteId] = useState(null);
  const [showModal, setShowModal] = useState(false);

  useEffect(() => {
    if (!loggedInData) {
      window.location.href = './welcome';
    }
  }, []);

  // 显示删除模态框
  const showDeleteModal = (id) => {
    setSelectedDeleteId(id);
    setShowModal(true);
  };

  // 隐藏模态框
  const hide = () => {
    setShowModal(false);
    setSelectedDeleteId(null);
  };

  // 执行删除操作
  const confirmDelete = () => {
    if (!selectedDeleteId) return;

    // 删除用户
    const updatedUsers = users.filter(user => user.id !== selectedDeleteId);
    setUsers(updatedUsers);
    localStorage.setItem("users", JSON.stringify(updatedUsers));

    // 删除关联聊天
    const targetUser = users.find(u => u.id === selectedDeleteId);
    const updatedChats = chats.filter(chat => chat.fullname !== targetUser?.fullname);
    setChats(updatedChats);
    localStorage.setItem("chats", JSON.stringify(updatedChats));

    // 删除关联上传
    const updatedUploads = uploads.filter(upload => upload.user !== targetUser?.email);
    setUploads(updatedUploads);
    localStorage.setItem("uploads", JSON.stringify(updatedUploads));

    hide();
  };

  return (
    <div className="login-success">
      <Nav />
      <div className="users-header">
        <h2 className="user-p">Users</h2>
      </div>
      <table className="table-wrapper">
        <thead>
          <tr className="table-row-header">
            <td className="first-column-width">Name</td>
            <td className="second-column-width">User Email ID</td>
            <td>Actions</td>
          </tr>
        </thead>
        <tbody id="table-body">
          {/* 用JSX渲染表格行,替代原生DOM操作 */}
          {users.map(user => (
            <tr key={user.id}>
              <td>{user.fullname}</td>
              <td>{user.email}</td>
              <td>
                <Link to={`./edituser?id=${user.id}`}>
                  <button className='edit-delete2'>Edit</button>
                </Link>
                {loggedInData.email !== user.email && (
                  <>
                    |
                    <button 
                      className="edit-delete2" 
                      id={`delete-${user.id}`} 
                      onClick={() => showDeleteModal(user.id)}
                    >
                      Delete
                    </button>
                  </>
                )}
              </td>
            </tr>
          ))}
          {/* 渲染空行 */}
          {Array.from({length: Math.max(10 - users.length, 0)}).map((_, index) => (
            <tr key={`empty-${index}`}>
              <td></td>
              <td></td>
              <td></td>
            </tr>
          ))}
        </tbody>
      </table>
      {/* 用状态控制模态框显示,替代原生DOM样式修改 */}
      <div 
        className="delete-modal-container" 
        id="delete-modal-container"
        style={{ visibility: showModal ? "visible" : "hidden" }}
      >
        <div className="confirm-deletion-wrapper">
          <p className="confirm-deletion-title">Confirm User Deletion</p>
          <button className="close-button-modal" onClick={hide}>
            ✕
          </button>
        </div>
        <div className="delete-modal-mid-content">
          <img src="./img/question-mark.png" alt="question-mark-logo" />
          <span>Are you sure?</span>
        </div>
        <div className="delete-modal-button-wrapper">
          {/* 移除Link,避免页面跳转 */}
          <button className="modal-button" id="ok-delete" onClick={confirmDelete}>
            Ok
          </button>
          <button className="modal-button" onClick={hide}>Cancel</button>
        </div>
      </div>
    </div>
  );
};

export default ManageUsers;

关键修改说明

  1. 用JSX渲染DOM:替代原生DOM操作,让React管理表格行和事件绑定,解决函数作用域问题。
  2. 状态驱动UI:用showModal状态控制模态框显示,用selectedDeleteId记录待删除用户ID,替代原生DOM样式修改。
  3. 正确更新状态:使用filter生成新数组,通过setUsers等更新状态,触发页面重渲染;避免直接修改原数组。
  4. 修复事件绑定:删除按钮的onClick用箭头函数传递用户ID,确保调用组件内的showDeleteModal函数。
  5. 修正模态框逻辑:移除OK按钮的Link包裹,直接绑定confirmDelete执行删除操作,避免页面跳转中断流程。
  6. 修复动态ID:将id={delete-${user.id}}改为正确的字符串拼接id={delete-${user.id}}。

内容的提问来源于stack exchange,提问作者Bry Zeos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:56:07