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

ReactJS中设置状态后Checkbox值未更新问题求助

问题描述

我开发的应用包含两个区域:左侧为分类栏,右侧展示对应分类下的项目。每个分类下设有全选和取消全选按钮,能看到代码中的状态已发生变更(已在HTML中格式化输出),但Checkbox的状态值并未更新,求解决。

相关代码

App.js

import { useEffect, useState, useMemo } from "react";
import { SidebarItem } from "./SideBarItem";
import { RightSection } from "./RightSection";
import "./styles.css";

export default function App() {
  const dummyJson = useMemo(() => {
    return {
      cat1: {
        id: "cat1",
        name: "Category 1",
        tiles: [
          {
            tileName: "abc",
            searchable: true,
            checked: false
          },
          {
            tileName: "def",
            searchable: true,
            checked: true
          }
        ]
      },
      cat2: {
        id: "cat2",
        name: "Category 2",
        tiles: [
          {
            tileName: "ab",
            searchable: true,
            checked: true
          },
          {
            tileName: "xyz",
            searchable: true,
            checked: false
          }
        ]
      },
      cat3: {
        id: "cat3",
        name: "Category 3",
        tiles: [
          {
            tileName: "lmn",
            searchable: true,
            checked: true
          },
          {
            tileName: "",
            searchable: false,
            checked: false
          }
        ]
      }
    };
  }, []);

  const [json, setJson] = useState(dummyJson);
  const [active, setActive] = useState(dummyJson["cat1"]);

  return (
    <>
      <div className="container">
        <div>
          <ul>
            {Object.values(json).map((details) => {
              const { id, name } = details;
              return (
                <SidebarItem
                  key={name}
                  name={name}
                  {...{
                    isActive: id === active.id,
                    setActive: () => setActive(details)
                  }}
                />
              );
            })}
          </ul>
        </div>
        <RightSection
          name={active.name}
          apps={active.tiles}
          {...{ json, setJson }}
        />
      </div>
      <p>{JSON.stringify(json, null, 2)}</p>
    </>
  );
}

RightSection.js

export const RightSection = ({ name, apps, json, setJson }) => {
  function handleSelectAll(categoryName, type) {
    const checked = type === "Select All" ? true : false;
    const updated = Object.fromEntries(
      Object.entries(json).map(([key, category]) => {
        if (category.name !== categoryName) {
          return [key, category];
        }
        const { name, tiles, ...rest } = category;
        return [
          key,
          {
            name,
            ...rest,
            tiles: tiles.map((item) => ({
              ...item,
              checked
            }))
          }
        ];
      })
    );
    setJson(updated);
  }

  return (
    <>
      <div>
        <input
          type="button"
          value={`select all under ${name}`}
          onClick={() => handleSelectAll(name, "Select All")}
        />
        <input
          type="button"
          value={`unselect all under ${name}`}
          onClick={() => handleSelectAll(name, "Unselect All")}
        />
        <h4 style={{ color: "blue" }}>{name} Items</h4>
        {apps.map((app) => {
          return (
            <section key={app.tileName}>
              <input checked={app.checked} type="checkbox" />
              <span key={app.tileName}>{app.tileName}</span> <br />
            </section>
          );
        })}
      </div>
    </>
  );
};
问题原因与解决方案

问题原因

点击全选/取消全选按钮后,json状态确实更新了,但右侧展示的apps来自active状态,而active还是初始时的对象引用,没有同步更新为json中最新的分类数据,导致Checkbox渲染的还是旧的checked值。

解决方案

推荐以下两种简洁的修复方式:

方式1:通过ID跟踪激活分类,实时从json取最新数据

修改App.js,将active状态替换为activeId,每次直接从json中读取对应ID的分类数据,避免状态不同步:

import { useEffect, useState, useMemo } from "react";
import { SidebarItem } from "./SideBarItem";
import { RightSection } from "./RightSection";
import "./styles.css";

export default function App() {
  const dummyJson = useMemo(() => {
    return {
      cat1: {
        id: "cat1",
        name: "Category 1",
        tiles: [
          {
            tileName: "abc",
            searchable: true,
            checked: false
          },
          {
            tileName: "def",
            searchable: true,
            checked: true
          }
        ]
      },
      cat2: {
        id: "cat2",
        name: "Category 2",
        tiles: [
          {
            tileName: "ab",
            searchable: true,
            checked: true
          },
          {
            tileName: "xyz",
            searchable: true,
            checked: false
          }
        ]
      },
      cat3: {
        id: "cat3",
        name: "Category 3",
        tiles: [
          {
            tileName: "lmn",
            searchable: true,
            checked: true
          },
          {
            tileName: "",
            searchable: false,
            checked: false
          }
        ]
      }
    };
  }, []);

  const [json, setJson] = useState(dummyJson);
  // 用ID跟踪激活分类,而非直接存储对象
  const [activeId, setActiveId] = useState("cat1");
  // 实时从json中获取最新的激活分类数据
  const active = json[activeId];

  return (
    <>
      <div className="container">
        <div>
          <ul>
            {Object.values(json).map((details) => {
              const { id, name } = details;
              return (
                <SidebarItem
                  key={name}
                  name={name}
                  {...{
                    isActive: id === activeId,
                    setActive: () => setActiveId(id)
                  }}
                />
              );
            })}
          </ul>
        </div>
        <RightSection
          name={active.name}
          apps={active.tiles}
          {...{ json, setJson }}
        />
      </div>
      <p>{JSON.stringify(json, null, 2)}</p>
    </>
  );
}

方式2:监听json变化,同步更新active状态

如果想保留原有active状态结构,可添加useEffect监听json变化,当json更新时同步刷新active:

import { useEffect, useState, useMemo } from "react";
import { SidebarItem } from "./SideBarItem";
import { RightSection } from "./RightSection";
import "./styles.css";

export default function App() {
  const dummyJson = useMemo(() => {
    return {
      cat1: {
        id: "cat1",
        name: "Category 1",
        tiles: [
          {
            tileName: "abc",
            searchable: true,
            checked: false
          },
          {
            tileName: "def",
            searchable: true,
            checked: true
          }
        ]
      },
      cat2: {
        id: "cat2",
        name: "Category 2",
        tiles: [
          {
            tileName: "ab",
            searchable: true,
            checked: true
          },
          {
            tileName: "xyz",
            searchable: true,
            checked: false
          }
        ]
      },
      cat3: {
        id: "cat3",
        name: "Category 3",
        tiles: [
          {
            tileName: "lmn",
            searchable: true,
            checked: true
          },
          {
            tileName: "",
            searchable: false,
            checked: false
          }
        ]
      }
    };
  }, []);

  const [json, setJson] = useState(dummyJson);
  const [active, setActive] = useState(dummyJson["cat1"]);

  // 监听json变化,同步更新active为最新分类数据
  useEffect(() => {
    setActive(json[active.id]);
  }, [json]);

  return (
    <>
      <div className="container">
        <div>
          <ul>
            {Object.values(json).map((details) => {
              const { id, name } = details;
              return (
                <SidebarItem
                  key={name}
                  name={name}
                  {...{
                    isActive: id === active.id,
                    setActive: () => setActive(details)
                  }}
                />
              );
            })}
          </ul>
        </div>
        <RightSection
          name={active.name}
          apps={active.tiles}
          {...{ json, setJson }}
        />
      </div>
      <p>{JSON.stringify(json, null, 2)}</p>
    </>
  );
}

两种方式都能让右侧Checkbox实时同步json中的checked状态,推荐方式1,它更简洁且避免了额外的状态同步逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:01:03