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

React(Next.js)批量插入PostgreSQL时页面计数器不渲染求助

解决React/Next.js批量插入数据时实时计数器不更新的问题

问题核心

你遇到的问题主要有三点:

  1. useRef无法触发重渲染:React不会监听useRef的current值变化,直接在JSX里渲染insertRows.current不会触发页面更新。
  2. useState闭包陷阱:同步循环里调用setInsRows(insRows+1)时,insRows始终是初始值,导致最终计数器只更新一次。
  3. 异步插入未正确等待:实际的insertToPSQL是异步函数,同步遍历会导致所有插入操作同时发起,无法准确跟踪每一条插入完成的时机。

解决方案

  1. 使用useState的函数式更新:避免闭包问题,确保每次更新都基于最新的计数器值。
  2. 异步遍历数据:用for...of替代forEach,等待每条数据插入完成后再更新计数器,保证进度实时性。
  3. 移除不必要的useRef:仅用useState维护计数器即可,React会自动触发重渲染。

修改后的完整代码

import { useState } from "react"

export default function InsertCounter() {
  const [insRows, setInsRows] = useState(0)

  // 模拟异步插入PostgreSQL的函数,替换为你的实际插入逻辑
  const insertToPSQL = async (row) => {
    await new Promise(resolve => setTimeout(resolve, 10)) // 模拟异步延迟
  }

  const addRows = async (data) => {
    try {
      // 异步遍历,确保每条插入完成后再更新计数器
      for (const row of data) {
        await insertToPSQL(row)
        // 函数式更新,基于最新状态值累加
        setInsRows(prev => prev + 1)
      }
    } catch (error) {
      console.error("插入失败:", error)
    } finally {
      alert(`已完成插入,共添加${insRows}条记录`)
      setInsRows(0) // 重置计数器
    }
  }

  const handleInsert = () => {
    setInsRows(0) // 开始插入前重置计数器
    addRows([
      { id: 1, name: "Roman" },
      { id: 2, name: "Misha" },
      { id: 3, name: "Vova" },
    ])
  }

  return (
    <div style={{ textAlign: "center", color: "blue" }}>
      <h2 style={{ color: "red" }}>插入计数器</h2>
      <button onClick={handleInsert} style={{ color: "yellow", backgroundColor: "blue" }}>
        开始插入
      </button>
      <div>已插入记录数: {insRows}</div>
    </div>
  )
}

关键说明

  • 函数式更新:setInsRows(prev => prev + 1)确保每次更新都使用最新的状态值,避免闭包导致的旧值问题。
  • 异步遍历:for...of配合await保证每条数据插入完成后再更新计数器,真实反映插入进度。
  • 移除useRef:React的useState会在状态变化时自动触发组件重渲染,无需额外使用useRef维护计数。

内容的提问来源于stack exchange,提问作者Роман

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 10:01:15