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
相关产品推荐
相关产品推荐

