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

React+MongoDB按钮仅首次点击更新数据库问题排查与修复

问题描述

作为React和MongoDB新手,尝试给MongoDB数据库中的用户有效期日期增加月份,但只有首次点击<Price>按钮时数据库会更新,后续点击无效,必须登出再重新登录才能再次更新(仍仅生效一次)。

问题原因

  • 后端更新无精准定位:updateActiveDate控制器中,User.updateOne({ $set: { activeUntil: req.body.activeUntil } })没有指定查询条件,会更新所有用户的有效期,而非当前登录用户;后续点击时数据库重复执行无效更新,前端也无法获取正确的用户最新数据。
  • 前端用户状态未同步:AuthContext中的user数据是登录时的缓存值,每次点击都基于旧的activeUntil计算新日期,导致请求参数错误;同时dateFormat不是React状态,页面显示无法自动更新。
  • 异步请求未等待完成:updateDate函数中调用axios.put时未加await,reFetch可能在更新请求完成前执行,无法获取最新数据。

修复方案

1. 修复后端更新控制器(精准更新当前用户)

修改updateActiveDate,通过URL参数中的namekey定位目标用户,更新后返回最新用户数据供前端同步:

import User from "../models/User.js";

export const updateActiveDate = async (req, res, next) => {
  try {
    // 按namekey定位当前用户,仅更新目标用户
    await User.updateOne(
      { namekey: req.params.namekey }, 
      { $set: { activeUntil: req.body.activeUntil } }
    );
    // 返回更新后的用户数据,用于前端同步状态
    const updatedUser = await User.findOne({ namekey: req.params.namekey });
    res.status(200).json(updatedUser);
  } catch (err) {
    next(err);
  }
};

2. 修复前端组件逻辑

将dateFormat改为React状态,等待更新请求完成后同步用户状态:

import React, { useContext, useState, useEffect } from "react";
import useFetch from "../../hooks/useFetch";
import Footer from "../../components/Footer";
import Navbar from "../../components/Navbar";
import Sidebar from "../../components/Sidebar";
import {
  ContractContainer,
  HeadingContainer,
  TypeH1,
  ActiveUntil,
  MonthlyWrapper,
  MonthlyContainer,
  MonthNumber,
  Price,
  Navbarback,
} from "./userinfoElements";
import { AuthContext } from "../../context/AuthContext";
import moment from "moment";
import axios from "axios";

const Userinfo = () => {
  const [isOpen, setIsOpen] = useState(false);
  const { user, dispatch } = useContext(AuthContext);
  // 将dateFormat改为React状态,确保页面响应更新
  const [dateFormat, setDateFormat] = useState("");
  const { data, loading } = useFetch(`/contracts/${user.contractType}`);

  // 初始化或用户状态变化时同步日期显示
  useEffect(() => {
    if (user?.activeUntil) {
      setDateFormat(moment(user.activeUntil).format("DD/MMMM/yyyy"));
    }
  }, [user]);

  const toggle = () => {
    setIsOpen(!isOpen);
  };

  const updateDate = async () => {
    try {
      // 基于最新的用户状态计算新日期
      const newDate = moment(user.activeUntil).add(1, "months");
      // 等待更新请求完成,获取后端返回的最新用户数据
      const res = await axios.put(`/activedate/${user.namekey}`, {
        activeUntil: newDate,
      });
      // 更新AuthContext中的用户状态,确保后续计算用最新值
      dispatch({
        type: "LOGIN_SUCCESS",
        payload: res.data,
      });
      // 更新页面显示的日期
      setDateFormat(newDate.format("DD/MMMM/yyyy"));
    } catch (err) {
      console.log(err);
    }
  };

  return (
    <>
      <Sidebar isOpen={isOpen} toggle={toggle} />
      <Navbar toggle={toggle} />
      <Navbarback />
      {loading ? (
        "Loading components, please wait"
      ) : (
        <>
          <ContractContainer>
            <HeadingContainer>
              <TypeH1>{data.contractType}</TypeH1>
              <ActiveUntil>Subscription active until {dateFormat}</ActiveUntil>
            </HeadingContainer>
            <MonthlyWrapper>
              <MonthlyContainer>
                <MonthNumber>1 Month</MonthNumber>
                <Price onClick={updateDate}>{data.month1Price}$</Price>
              </MonthlyContainer>
              <MonthlyContainer>
                <MonthNumber>3 Month</MonthNumber>
                <Price onClick={updateDate}>{data.month3Price}$</Price>
              </MonthlyContainer>
              <MonthlyContainer>
                <MonthNumber>6Month</MonthNumber>
                <Price onClick={updateDate}>{data.month6Price}$</Price>
              </MonthlyContainer>
              <MonthlyContainer>
                <MonthNumber>12Month</MonthNumber>
                <Price onClick={updateDate}>{data.month12Price}$</Price>
              </MonthlyContainer>
            </MonthlyWrapper>
          </ContractContainer>
        </>
      )}
      <Footer />
    </>
  );
};

export default Userinfo;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:31:27