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

React中布尔数组状态初始化为空数组,求原因及解决方案

问题分析与解决方案

你的核心问题是**checkedItems状态初始化后始终为空数组**,原因在于:

  • 组件首次渲染时,productList的初始值是空数组[],所以new Array(productList.length).fill(false)生成的是空数组,而useState的初始值只会在组件首次挂载时生效,后续productList通过API获取到数据后,不会自动重新初始化checkedItems。
  • 另外你当前的handleOnChange里的reduce逻辑存在错误,无法正确收集选中的SKU列表。

修复步骤

1. 同步checkedItems与productList的长度

添加一个useEffect监听productList的变化,当产品列表加载完成后,初始化checkedItems为对应长度的false数组:

useEffect(() => {
  // 当productList有数据时,初始化checkedItems为对应长度的false数组
  if (productList.length > 0) {
    setCheckedItems(new Array(productList.length).fill(false));
  }
}, [productList]);

2. 修正checkedItems的初始化方式

直接初始化为空数组即可,后续通过上面的useEffect同步:

const [checkedItems, setCheckedItems] = useState<boolean[]>([]);

3. 修复选中SKU的收集逻辑

原来的reduce函数缺少初始值,且逻辑错误,无法正确收集所有选中的SKU。修改handleOnChange中的skuList生成逻辑:

const handleOnChange = (position: number) => {
  const updatedCheckedItems = checkedItems.map((item, index) =>
    index === position ? !item : item
  );

  setCheckedItems(updatedCheckedItems);

  // 收集所有选中的产品SKU
  const skuList = productList.filter((_, index) => updatedCheckedItems[index])
    .map(item => item.sku);

  setDeleteList(skuList);
};

4. 可选:优化复选框的checked属性判断

避免checkedItems[index]出现undefined的情况,可以添加默认值:

checked={checkedItems[index] ?? false}

完整修复后的代码

import React, { useState, useEffect } from "react";
import { Container, ItemDescription, ProductContainer } from "./style";
const API = "http://localhost:4000/select";

interface DATA {
  sku: string;
  name: string;
  price: string;
  type: string;
  size?: number; // 可选字段,避免类型报错
  weight?: number;
  height?: number;
  width?: number;
  length?: number;
}

interface IProps {
  del: boolean;
}

const ProductDisplay = ({ del }: IProps) => {
  const [productList, setProductList] = useState<Array<DATA>>([]);
  const [checkedItems, setCheckedItems] = useState<boolean[]>([]);
  const [deleteList, setDeleteList] = useState<string[]>([]); // 改为string数组存储SKU

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(API);
        const results = await response.json();
        setProductList(results);
      } catch (e) {
        console.log(e);
      }
    };
    fetchData();
  }, []);

  // 当产品列表更新时,同步更新checkedItems的长度
  useEffect(() => {
    if (productList.length > 0) {
      setCheckedItems(new Array(productList.length).fill(false));
    }
  }, [productList]);

  const handleOnChange = (position: number) => {
    const updatedCheckedItems = checkedItems.map((item, index) =>
      index === position ? !item : item
    );

    setCheckedItems(updatedCheckedItems);

    // 收集所有选中的SKU
    const selectedSkus = productList
      .filter((_, idx) => updatedCheckedItems[idx])
      .map(product => product.sku);

    setDeleteList(selectedSkus);
  };

  return (
    <div>
      {productList.length === 0 && <h4>Fetching Checkboxes ...</h4>}
      {productList.length > 0 && (
        <Container>
          {productList.map((item, index) => (
            <ProductContainer key={item.sku}> {/* 添加唯一key */}
              <input
                type="checkbox"
                value={item.sku}
                id={`custom-checkbox-${index}`}
                checked={checkedItems[index] ?? false}
                onChange={() => handleOnChange(index)}
              />
              <ItemDescription>
                <span className="sku">{item.sku}</span>
                <span className="name">{item.name}</span>
                <span className="price">{item.price} $</span>
                {item.size && <span className="size">Size: {item.size}MB</span>}
                {item.weight && <span className="weight">Weight: {item.weight}KG</span>}
                {item.height && (
                  <span className="dimention">
                    Dimention: {item.height} x {item.width} x {item.length}
                  </span>
                )}
              </ItemDescription>
            </ProductContainer>
          ))}
        </Container>
      )}
    </div>
  );
};

export default ProductDisplay;

额外说明

  • 给DATA接口的可选字段添加?,避免类型报错;
  • 给列表项添加key属性(用item.sku,保证唯一性),符合React列表渲染规范;
  • deleteList改为string[]类型,因为只需要存储SKU字符串;
  • setCheckedItems是异步操作,所以在handleOnChange中直接打印checkedItems会显示更新前的状态,如果需要查看更新后的状态,可以添加一个监听checkedItems的useEffect。

内容的提问来源于stack exchange,提问作者Leon Murelli SIlveira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:07:08