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

React函数组件useState无法在内部函数中切换布尔状态值

问题根因

布尔值无法正常翻转是典型的React函数组件闭包陷阱,由两个细节问题共同导致:

  • columns配置在组件首次渲染时生成后就没有更新过,传入的buttonFollow格式化函数始终缓存着首次渲染作用域里的isPresent初始值true,点击触发时拿不到后续更新的状态。
  • setIsPresent是异步操作,调用后立刻打印isPresent时,状态还未完成更新,拿到的永远是当前渲染周期的旧值。

类组件不存在这个问题,是因为类方法通过this.state读取状态,this始终指向最新的组件实例,不会被闭包缓存旧值。

修复方案

做三处调整即可:

  1. 状态更新使用函数式写法,不依赖闭包中的旧状态值
  2. 用useMemo包裹columns配置,将isPresent加入依赖项,保证状态变化后列配置会重新生成,绑定的事件函数能拿到最新作用域
  3. 用useEffect监听状态变化获取最新值,不要在setState调用后立刻读取状态

修复后的完整代码:

import React, { useState, useMemo, useEffect } from "react";
import BootstrapTable from "react-bootstrap-table-next";
import "bootstrap/dist/css/bootstrap.min.css";
import "react-bootstrap-table-next/dist/react-bootstrap-table2.min.css";
import { Button } from "react-bootstrap";

export default function App() {
  const [isPresent, setIsPresent] = useState(true);

  // 监听状态变化,打印最新值
  useEffect(() => {
    console.log("当前isPresent值:", isPresent);
  }, [isPresent]);

  const onFollowChanged = () => {
    // 函数式更新,始终基于最新状态翻转,不受闭包旧值影响
    setIsPresent(prev => !prev);
  };

  // 列配置随isPresent变化重新生成
  const columns = useMemo(() => [
    {
      dataField: "id",
      text: "id",
      sort: true
    },
    {
      dataField: "fName",
      text: "First Name",
      sort: true
    },
    {
      dataField: "lName",
      text: "Last Name"
    },
    {
      dataField: "grade",
      text: "Grade",
      sort: true
    },
    {
      dataField: "present",
      text: "Present",
      formatter: () => <Button onClick={onFollowChanged}>Present</Button>
    }
  ], [isPresent]);

  const students = [
    { id: 100, fName: "John", lName: "Doe", grade: "first" },
    { id: 200, fName: "Jane", lName: "Doe", grade: "second" },
    { id: 300, fName: "Peter", lName: "Paker", grade: "third" },
    { id: 400, fName: "Clark", lName: "Kent", grade: "fourth" },
    { id: 500, fName: "LeBron", lName: "James", grade: "fifth" }
  ];

  return (
    <div>
      <BootstrapTable keyField="id" data={students} columns={columns} />
    </div>
  );
}
注意事项

所有依赖组件内部状态的配置项(比如本例中带自定义按钮渲染的表格列配置),都要保证状态更新时配置同步重新生成,否则很容易触发闭包陷阱,始终拿到旧的状态值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:09:28