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

React/Next.js中作品激活状态更新后页面刷新失效问题求助

问题分析与修复方案

你遇到的问题核心是数据库中的Brainstorm状态并没有真正被更新,所以页面刷新后会回到初始值。结合你的代码来看,主要有两个关键问题:API路由的更新逻辑错误,以及前端组件的调用逻辑存在缺陷。

1. 修复API路由的核心错误

你的API路由在更新Brainstorm时,错误地使用了用户ID作为查询条件,而不是目标Brainstorm的ID。这会导致你试图更新一条不存在的Brainstorm记录(因为Brainstorm的ID和用户ID是完全不同的字段),数据库操作实际上没有生效。

修改后的API路由代码:

import { NextApiRequest, NextApiResponse } from "next";
import { decryptCookie } from "../../../lib/cookie";
import { prisma } from "../../../lib/prisma";
interface User { email: string; issuer: string; }
export default async (req: NextApiRequest, res: NextApiResponse) => {
  if (req.method !== "PUT") return res.status(405).end(); // 修复end()调用的语法错误

  try {
    const userFromCookie = await decryptCookie(req.cookies.auth);
    if (!userFromCookie.email) {
      throw new Error("Cannot find user. Unable to proceed with update.");
    }
    const userEmail = userFromCookie.email;
    // 从请求体中获取要更新的active状态和brainstormId
    const { active, brainstormId } = JSON.parse(req.body);

    // 先校验用户权限:确保当前用户拥有该Brainstorm
    const user = await prisma.user.findUnique({ where: { email: userEmail } });
    const targetBrainstorm = await prisma.brainstorm.findFirst({
      where: {
        id: brainstormId,
        userId: user.id
      }
    });

    if (!targetBrainstorm) {
      return res.status(403).json({ message: "You don't have permission to update this brainstorm" });
    }

    // 更新指定的Brainstorm记录(使用brainstormId作为查询条件)
    const updatedBrainstorm = await prisma.brainstorm.update({
      data: { active },
      where: { id: brainstormId },
    });

    res.status(200).json({ response: updatedBrainstorm }); // 用200表示更新成功,201用于创建资源
  } catch (error) {
    console.error(error);
    return res.status(500).json({ message: error.message }); // 返回JSON格式错误信息,方便前端处理
  }
};

关键修改点:

  • 从请求体接收brainstormId,明确要更新的目标Brainstorm
  • 更新逻辑使用brainstormId而非用户ID作为查询条件
  • 增加权限校验,确保用户只能修改自己创建的Brainstorm
  • 修正状态码使用(200对应更新成功)和语法错误
  • 优化错误处理,返回标准化的JSON错误信息

2. 修复前端组件的调用逻辑

你的前端组件存在两个问题:一是没有传递brainstormId给API,二是setState的异步特性导致传递给API的active值是旧的,同时缺少API调用失败的回滚逻辑。

修改后的组件核心代码:

import React, { useState } from "react";
import Switch from "react-switch";
import { Container, BrainstormInfo, BrainstormTitle, Active, Group, StormPieces, } from "./styles";
import { Brainstorm } from "../../pages/user-dashboard";
import useFormatDate from "../../hooks/useFormatDate";

interface Props { brainstormData: Brainstorm; }
const UserBrainstormCard: React.FC<Props> = ({ brainstormData }) => {
  if (!brainstormData) return <h1>Loading...</h1>;
  const [active, setActive] = useState(brainstormData.active);
  const [isUpdating, setIsUpdating] = useState(false); // 添加加载状态
  const formatedDate = useFormatDate( (brainstormData.createdAt as unknown) as string );

  async function handleActiveness() {
    if (isUpdating) return; // 防止重复点击
    const newActiveState = !active;
    setIsUpdating(true);
    setActive(newActiveState); // 乐观更新UI

    try {
      const response = await fetch("/api/brainstorm/update", { 
        method: "PUT", 
        headers: {
          "Content-Type": "application/json", // 必须设置该头,否则后端无法解析JSON
        },
        body: JSON.stringify({ 
          active: newActiveState,
          brainstormId: brainstormData.id // 传递目标Brainstorm的ID
        }), 
      });

      if (!response.ok) {
        throw new Error("Failed to update brainstorm status");
      }

      const data = await response.json();
      setActive(data.response.active); // 用数据库返回的状态同步UI
    } catch (error) {
      console.error(error);
      setActive(active); // API调用失败,回滚UI状态
      alert("Failed to update status, please try again");
    } finally {
      setIsUpdating(false); // 结束加载状态
    }
  }

  return (
    <Container>
      <BrainstormInfo>
        <p>Brainstorm</p>
        <p>{formatedDate}</p>
      </BrainstormInfo>
      <BrainstormTitle>
        <h3>{brainstormData.title}</h3>
      </BrainstormTitle>
      <Active>
        <Group>
          <p>Active:</p>
          <Switch 
            offHandleColor="#eee" 
            onHandleColor="#eee" 
            draggable={false} 
            onChange={handleActiveness} 
            checked={active} 
            checkedIcon={false} 
            uncheckedIcon={false} 
            height={15} 
            width={30} 
            handleDiameter={20} 
            offColor="#f13030" 
            onColor="#2dea8f"
            disabled={isUpdating} // 加载时禁用按钮
          />
        </Group>
        <StormPieces>
          <p> {brainstormData.stormPieces.length} Stormpieces </p>
        </StormPieces>
      </Active>
    </Container>
  );
};
export default UserBrainstormCard;

关键修改点:

  • 提前计算newActiveState,避免setState异步导致的旧值问题
  • 添加Content-Type请求头,确保后端正确解析请求体
  • 传递brainstormId给API,明确更新目标
  • 增加加载状态和重复点击拦截,优化用户体验
  • 添加错误回滚逻辑:API调用失败时恢复UI状态
  • 移除未使用的produce依赖

3. 额外优化建议

  • 父组件可以在子组件更新状态后,重新拉取Brainstorm列表,确保所有子组件状态同步
  • 考虑使用React Query或SWR这类状态管理库,自动处理服务器状态的缓存和重新验证,减少手动同步的工作量
  • 可以将API调用逻辑封装成自定义hooks,提高代码复用性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:12:31