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

React+Apollo项目中删除用户Mutation提前执行的修复问询

问题描述

基于ReactJS和Apollo Client开发项目,实现deleteUser功能时,删除Mutation能正常运行,但缺少确认Modal环节。需求是:管理员点击删除按钮弹出确认Modal,仅在点击Modal内的“Yes”按钮后执行删除Mutation。

当前存在的问题:

  • 点击删除用户按钮时,删除Mutation会先执行,之后才弹出确认Modal
  • 点击Modal的“Yes”按钮仅触发数据重新获取(refetch),没有实际执行删除逻辑

解决方案

核心思路是把「触发删除」和「执行删除」拆分:点击删除按钮只弹出确认框,确认后才调用删除Mutation。以下是修改后的完整代码:

import React, { useState } from "react";
import { Table, Button } from "react-bootstrap";
import { useMutation } from "@apollo/client";

import { GET_ALL_USERS } from "../../../gql/query";
import { DELETE_USER } from "../../../gql/mutation";

import ModalEdit from "../Modals/ModalEdit";
import ModalConfirm from "../../Common/Modals/ModalConfirm";

const TableUserInfo = ({ data, variables }) => {
  const [showEditModal, setShowEditModal] = useState(false);
  const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false);
  const [targetUsername, setTargetUsername] = useState("");

  const [deleteUser, { error, loading }] = useMutation(DELETE_USER);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error</p>;

  if (
    !data ||
    !data.getAllUsers ||
    !data.getAllUsers.rows ||
    !data.getAllUsers.rows.length
  ) {
    return <p className="text-center"> Tidak ada data tersedia </p>;
  }

  // 点击删除按钮:仅弹出确认框,不执行删除
  const handleOpenDeleteConfirm = (username) => {
    setTargetUsername(username);
    setShowDeleteConfirmModal(true);
  };

  // 确认删除:执行Mutation并更新缓存
  const handleConfirmDelete = () => {
    deleteUser({
      variables: { username: targetUsername },
      update(cache, { data }) {
        const { getAllUsers } = cache.readQuery({
          query: GET_ALL_USERS,
          variables,
        });

        cache.writeQuery({
          query: GET_ALL_USERS,
          variables,
          data: {
            getAllUsers: {
              ...getAllUsers,
              totalItems: getAllUsers.totalItems - 1,
              rows: getAllUsers.rows.filter(user => user.username !== targetUsername)
            }
          }
        });
      },
      onError: (error) => {
        console.log(JSON.stringify(error, null, 2));
      },
    });
    // 执行完删除后关闭Modal
    setShowDeleteConfirmModal(false);
  };

  return (
    <Table responsive>
      <thead>
        <tr>
          <th>No</th>
          <th>Nama Pengguna</th>
          <th>Role Akun</th>
          <th>Email</th>
          <th>Tanggal Daftar</th>
          <th>Status Akun</th>
          <th>Pengaturan</th>
        </tr>
      </thead>
      <tbody>
        {data.getAllUsers.rows.map((user, index) => (
          <tr key={user.username}>
            <td>{index + 1}</td>
            <td>{user.full_name}</td>
            <td>{user.group_id}</td>
            <td>{user.email}</td>
            <td>{user.created_dtm}</td>
            <td>{user.status}</td>
            <td>
              {user.status !== "ACTIVE"
                ? [
                    <Button
                      key="Aktifkan Akun"
                      className="d-block mb-2 text-white bg-secondary w-100"
                    >
                      Aktifkan Akun
                    </Button>,
                    <Button
                      key="Ganti Role Akun"
                      className="d-block mb-2 btn-block btn-sm w-100"
                      disabled
                    >
                      Ganti Role Akun
                    </Button>,
                  ]
                : user.group_id === "admin"
                ? [
                    <Button
                      key="Ganti Role Akun"
                      variant="outline-success"
                      className="d-block btn-sm mb-2 w-100"
                    >
                      Ganti Role Akun
                    </Button>,
                  ]
                : [
                    <Button
                      key="Pilih Role Akun"
                      className="d-block btn-sm mb-2 w-100"
                    >
                      Pilih Role Akun
                    </Button>,
                  ]}
              <Button
                key="Edit"
                variant="outline-primary"
                onClick={() => {
                  setShowEditModal(true);
                  setTargetUsername(user.username);
                }}
                className="d-block btn-block btn-sm mb-2 w-100"
                disabled={loading}
              >
                Edit
              </Button>
              <Button
                key="Hapus"
                variant="outline-danger"
                onClick={() => handleOpenDeleteConfirm(user.username)}
                disabled={loading}
                className="d-block btn-block btn-sm mb-2 w-100"
              >
                Hapus
              </Button>
            </td>
          </tr>
        ))}
      </tbody>
      {/* 编辑Modal */}
      {showEditModal && (
        <ModalEdit
          show={showEditModal}
          onClose={() => setShowEditModal(false)}
          username={targetUsername}
        />
      )}
      {/* 删除确认Modal */}
      {showDeleteConfirmModal && (
        <ModalConfirm 
          show={showDeleteConfirmModal}
          onHide={() => setShowDeleteConfirmModal(false)}
          onConfirm={handleConfirmDelete}
          userToDelete={targetUsername}
        />
      )}
    </Table>
  );
};

export default TableUserInfo;

关键改动说明

  1. 拆分状态管理:把编辑和删除的Modal状态分开(showEditModal、showDeleteConfirmModal),避免状态冲突;用targetUsername统一存储当前操作的用户名
  2. 修改删除触发逻辑:点击「Hapus」按钮时调用handleOpenDeleteConfirm,仅弹出确认框,不执行删除Mutation
  3. 新增确认执行逻辑:handleConfirmDelete函数专门处理确认后的删除操作,执行Mutation并更新缓存,完成后关闭Modal
  4. 调整Modal参数传递:给ModalConfirm传递onConfirm回调,替代原来的handleDelete,确保点击「Yes」时才触发删除

内容的提问来源于stack exchange,提问作者github.arief

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 18:20:34