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

React Hooks环境下取消勾选复选框时Bar chart无法更新的问题求助

核心问题梳理

  • 复选框切换逻辑错误:toggleMale 错误将布尔类型的maleIsChecked赋值为数组chartData,导致取消勾选永远不生效;toggleAll 错误将数组类型的chartData赋值为布尔值,直接破坏了原始数据源。
  • 视图与状态未绑定:女性复选框的checked属性被注释,勾选状态无法和femaleIsChecked同步。
  • 副作用逻辑冲突:三个useEffect各自独立处理百分比计算,取消勾选时没有对应的恢复逻辑,导致状态更新混乱。
  • 变量初始化不规范:人数计数器初始化为空数组,依赖隐式类型转换才能正常计数,存在潜在隐患。

修正后完整代码

import React, { useEffect, useState } from "react";
import { Bar } from "react-chartjs-2";

// 固定原始数据不需要存state
const jsonData = [
  { gender: "female" },
  { gender: "male" },
  { gender: "female" },
  { gender: "male" },
  { gender: "female" },
  { gender: "male" },
  { gender: "female" },
  { gender: "female" },
  { gender: "female" },
  { gender: "female" },
];

const RandomStatic = (props) => {
  const [femalePercentage, setFemalePercentage] = useState(0);
  const [malePercentage, setMalePercentage] = useState(0);
  const [femaleIsChecked, setFemaleIsChecked] = useState(false);
  const [maleIsChecked, setMaleIsChecked] = useState(false);
  const [allIsChecked, setAllIsChecked] = useState(false);

  // 统一处理百分比计算,仅依赖三个勾选状态
  useEffect(() => {
    // 先统计原始数据的男女总数
    let fCount = 0, mCount = 0;
    jsonData.forEach(item => {
      if (item.gender === 'female') fCount++;
      else mCount++;
    });
    const total = fCount + mCount;

    // 根据勾选状态赋值百分比
    if (allIsChecked || (femaleIsChecked && maleIsChecked)) {
      // 两者都展示:按原始占比计算
      setFemalePercentage((fCount / total) * 100);
      setMalePercentage((mCount / total) * 100);
      // 同步勾选状态
      setFemaleIsChecked(true);
      setMaleIsChecked(true);
      setAllIsChecked(true);
    } else if (femaleIsChecked) {
      // 仅展示女性
      setFemalePercentage(100);
      setMalePercentage(0);
      setAllIsChecked(false);
    } else if (maleIsChecked) {
      // 仅展示男性
      setFemalePercentage(0);
      setMalePercentage(100);
      setAllIsChecked(false);
    } else {
      // 都不勾选:归零
      setFemalePercentage(0);
      setMalePercentage(0);
      setAllIsChecked(false);
    }
  }, [femaleIsChecked, maleIsChecked, allIsChecked]);

  // 切换逻辑简化
  const toggleFemale = () => setFemaleIsChecked(prev => !prev);
  const toggleMale = () => setMaleIsChecked(prev => !prev);
  const toggleAll = () => setAllIsChecked(prev => !prev);

  return (
    <div>
      <Bar
        className="chart"
        data={{
          labels: ["Female", "Male"],
          datasets: [
            {
              data: [femalePercentage, malePercentage],
              backgroundColor: ["green", "yellow"],
              borderColor: ["green", "yellow"],
              borderWidth: 0.5,
            },
          ],
        }}
        options={{
          responsive: true,
          maintainAspectRatio: false,
          plugins: {
            title: {
              display: true,
              text: "Male and Female Ratio",
            },
            legend: {
              display: false,
            },
          },
          scales: {
            y: {
              display: true,
              title: {
                display: true,
                text: "Percentage",
              },
              min: 0,
              max: 100
            },
            x: {
              display: true,
              title: {
                display: true,
                text: "Population",
              },
            },
          },
          showTooltips: false,
          hover: false,
        }}
      />
      <div className="checkbox-form-wrapper">
        <div className="chartBox">
          <label>Female Only</label>
          <input
            name="femalePercentage"
            type="checkbox"
            checked={femaleIsChecked}
            onChange={toggleFemale}
          />
          <label>Male Only</label>
          <input
            name="malePercentage"
            type="checkbox"
            checked={maleIsChecked}
            onChange={toggleMale}
          />
          <label>Both Female and Male</label>
          <input
            name="allData"
            type="checkbox"
            checked={allIsChecked}
            onChange={toggleAll}
          />
        </div>
      </div>
    </div>
  );
};

export default RandomStatic;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 23:06:05