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

如何基于现有代码实现Chakra-UI二级嵌套Checkbox联动功能

二级嵌套复选框联动实现方案(基于Chakra-UI)

需求说明

  • 点击父复选框时,所有子项(含二级子项)被选中
  • 点击单个二级子项时,对应一级父项切换为不确定状态
  • 某一级所有子项选中时,该级父项自动变为选中状态

现有代码状态

已完成第一级复选框联动逻辑,需扩展实现二级子项的联动功能,现有代码如下:

import React from "react";
import { Checkbox, Stack, Box } from "@chakra-ui/react";

const data = {
users: [
{
  id: "user-1",
  name: "User 1",
  child: [{ name: "Salary1" }, { name: "Department1" }]
},
{
  id: "user-2",
  name: "User 2",
  child: [{ name: "Salary2" }, { name: "Department2" }]
},
{
  id: "user-3",
  name: "User 3",
  child: [{ name: "Salary3" }, { name: "Department3" }]
},
{
  id: "user-4",
  name: "User 4",
  child: [{ name: "Salary4" }, { name: "Department4" }]
},
{
  id: "user-5",
  name: "User 5",
  child: [{ name: "Salary5" }, { name: "Department5" }]
},
{
  id: "user-6",
  name: "User 6",
  child: [{ name: "Salary6" }, { name: "Department6" }]
},
{
  id: "user-7",
  name: "User 7",
  child: [{ name: "Salary7" }, { name: "Department7" }]
},
{
  id: "user-8",
  name: "User 8",
  child: [{ name: "Salary8" }, { name: "Department8" }]
}
 ]
};

export default function App() {
const [checkedItems, setCheckedItems] = React.useState(
  data.users.map(() => false)
 );

const allChecked = checkedItems.every(Boolean);
const isIndeterminate = checkedItems.some(Boolean) && !allChecked;

return (
  <Stack pt={3} pl={3}>
  <Checkbox
    isChecked={allChecked}
    isIndeterminate={isIndeterminate}
    onChange={(e) =>
      setCheckedItems(data.users.map(() => e.target.checked))
    }
  >
    Parent Checkbox
  </Checkbox>

  <Stack pl={6} mt={2} spacing={2}>
    {data.users.map((user, index) => (
      <Box key={user.id}>
        <Checkbox
          key={user.id}
          isChecked={checkedItems[index]}
          onChange={(e) =>
            setCheckedItems([
              ...checkedItems.slice(0, index),
              e.target.checked,
              ...checkedItems.slice(index + 1)
            ])
          }
        >
          {user.name}
        </Checkbox>
        <Stack pl={6} spacing={2}>
          {user.child.map((category) => (
            <Checkbox key={category.name}>{category.name}</Checkbox>
          ))}
        </Stack>
      </Box>
    ))}
  </Stack>
</Stack>
);
}

解决方案:修改后的完整代码

import React from "react";
import { Checkbox, Stack, Box } from "@chakra-ui/react";

const data = {
users: [
{
  id: "user-1",
  name: "User 1",
  child: [{ name: "Salary1" }, { name: "Department1" }]
},
{
  id: "user-2",
  name: "User 2",
  child: [{ name: "Salary2" }, { name: "Department2" }]
},
{
  id: "user-3",
  name: "User 3",
  child: [{ name: "Salary3" }, { name: "Department3" }]
},
{
  id: "user-4",
  name: "User 4",
  child: [{ name: "Salary4" }, { name: "Department4" }]
},
{
  id: "user-5",
  name: "User 5",
  child: [{ name: "Salary5" }, { name: "Department5" }]
},
{
  id: "user-6",
  name: "User 6",
  child: [{ name: "Salary6" }, { name: "Department6" }]
},
{
  id: "user-7",
  name: "User 7",
  child: [{ name: "Salary7" }, { name: "Department7" }]
},
{
  id: "user-8",
  name: "User 8",
  child: [{ name: "Salary8" }, { name: "Department8" }]
}
 ]
};

export default function App() {
// 调整状态结构:二维数组,对应每个用户下的子项选中状态
const [checkedItems, setCheckedItems] = React.useState(
  data.users.map(user => user.child.map(() => false))
);

// 计算顶层复选框状态:所有子项全选则顶层选中,部分选则不确定
const allTopChecked = checkedItems.every(userItems => userItems.every(Boolean));
const isTopIndeterminate = checkedItems.some(userItems => userItems.some(Boolean)) && !allTopChecked;

return (
  <Stack pt={3} pl={3}>
    <Checkbox
      isChecked={allTopChecked}
      isIndeterminate={isTopIndeterminate}
      onChange={(e) => {
        // 点击顶层复选框时,同步所有一级和二级子项状态
        const newState = data.users.map(user => 
          user.child.map(() => e.target.checked)
        );
        setCheckedItems(newState);
      }}
    >
      Parent Checkbox
    </Checkbox>

    <Stack pl={6} mt={2} spacing={2}>
      {data.users.map((user, userIndex) => {
        // 计算当前用户复选框的状态
        const userAllChecked = checkedItems[userIndex].every(Boolean);
        const userIsIndeterminate = checkedItems[userIndex].some(Boolean) && !userAllChecked;

        return (
          <Box key={user.id}>
            <Checkbox
              isChecked={userAllChecked}
              isIndeterminate={userIsIndeterminate}
              onChange={(e) => {
                // 点击用户复选框时,同步其下所有子项状态
                const newUserItems = user.child.map(() => e.target.checked);
                const newState = [
                  ...checkedItems.slice(0, userIndex),
                  newUserItems,
                  ...checkedItems.slice(userIndex + 1)
                ];
                setCheckedItems(newState);
              }}
            >
              {user.name}
            </Checkbox>
            <Stack pl={6} spacing={2}>
              {user.child.map((category, childIndex) => (
                <Checkbox
                  key={category.name}
                  isChecked={checkedItems[userIndex][childIndex]}
                  onChange={(e) => {
                    // 点击二级子项时,更新对应位置的状态
                    const newUserItems = [
                      ...checkedItems[userIndex].slice(0, childIndex),
                      e.target.checked,
                      ...checkedItems[userIndex].slice(childIndex + 1)
                    ];
                    const newState = [
                      ...checkedItems.slice(0, userIndex),
                      newUserItems,
                      ...checkedItems.slice(userIndex + 1)
                    ];
                    setCheckedItems(newState);
                  }}
                >
                  {category.name}
                </Checkbox>
              ))}
            </Stack>
          </Box>
        );
      })}
    </Stack>
  </Stack>
);
}

关键改动说明

  1. 状态结构优化:将原来的一维布尔数组改为二维数组,每个一级用户对应一个子数组,存储其下二级子项的选中状态,更贴合嵌套结构
  2. 一级复选框联动:点击一级用户复选框时,自动同步其下所有二级子项的选中状态,同时根据子项状态计算自身的isChecked和isIndeterminate
  3. 二级子项联动:点击二级子项时,更新对应位置的状态,并实时触发一级复选框的状态重新计算,实现部分选中时的不确定状态
  4. 顶层复选框逻辑升级:点击顶层复选框时,同时选中/取消所有一级和二级复选框,保持全层级联动

内容的提问来源于stack exchange,提问作者Claude Vernet Michel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 00:20:56