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

如何基于数组创建多个React useState或用单状态对象管理组件状态?

解决方案

1. 将多个状态合并为单个对象

无需单独声明多个useState,可以基于options数组自动生成一个包含所有筛选器的状态对象,维护更便捷:

// 根据options自动生成初始筛选状态,每个选项的name作为键,初始值为空数组
const [allFilters, setAllFilters] = React.useState(
  options.reduce((acc, option) => {
    acc[option.name] = [];
    return acc;
  }, {})
);

2. 仅更新单个筛选器属性

编写专门的更新函数,通过函数式更新语法修改目标属性,同时保留其他状态不变:

// 接收筛选器key和新值,精准更新对应属性
const updateFilter = (filterKey, newValue) => {
  setAllFilters(prevState => ({
    ...prevState, // 展开原有状态,保留其他属性
    [filterKey]: newValue // 替换目标属性的新值
  }));
};

3. 基于数组循环创建customFilter

直接遍历options数组,为每个选项渲染customFilter组件,传入对应的状态和绑定好的更新函数:

// 在return中循环渲染所有筛选器
return (
  <>
    {options.map(option => (
      customFilter(
        option,
        allFilters[option.name],
        (newValue) => updateFilter(option.name, newValue)
      )
    ))}
  </>
);

完整修改后的代码

import * as React from 'react';

import TransferList from './TransferList';
import Accordion from '@mui/material/Accordion';
import AccordionSummary from '@mui/material/AccordionSummary';
import AccordionDetails from '@mui/material/AccordionDetails';
import Typography from '@mui/material/Typography';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';

export default function CustomFormatBox() {
  const options = [
    {
      name: 'sample_type_key',
      label: 'Sample Type',
      defaultOperator: 'in',
      valueEditorType: 'multiselect',
      values: [
        { name: '0', label: 'OPTICAL_BLANK_0' },
        { name: '1', label: 'OPTICAL_BLANK_1' },
      ],
    },
    {
      name: 'cuvette_number',
      label: 'Cuvette Number',
      defaultOperator: 'in',
      valueEditorType: 'multiselect',
      values: [
        { name: '0', label: '0' },
        { name: '1', label: '1' },
        { name: '2', label: '2' },
      ],
    },
    {
      name: 'wavelength_key',
      label: 'Wavelength',
      values: [
        { name: '0', label: '340nm' },
        { name: '8', label: '850nm' },
      ],
    },
  ];

  // 自动生成初始筛选状态
  const [allFilters, setAllFilters] = React.useState(
    options.reduce((acc, option) => {
      acc[option.name] = [];
      return acc;
    }, {})
  );

  // 单个筛选器更新函数
  const updateFilter = (filterKey, newValue) => {
    setAllFilters(prevState => ({
      ...prevState,
      [filterKey]: newValue
    }));
  };

  const customFilter = (option, right, setRight) => (
    <Accordion key={option.name}> {/* 添加唯一key避免React警告 */}
      <AccordionSummary
        expandIcon={<ArrowDownwardIcon />}
        aria-controls={`panel-${option.label}-content`}
        id={`panel-${option.label}-header`}
      >
        <Typography>{option.label}</Typography>
      </AccordionSummary>
      <AccordionDetails>
        <TransferList option={option} right={right} setRight={setRight} />
        <table>
          <tbody>
            {right.map((item) => (
              <tr key={item.name}>
                <td>{item.label}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </AccordionDetails>
    </Accordion>
  );

  return (
    <>
      {/* 循环渲染所有筛选器 */}
      {options.map(option => 
        customFilter(
          option,
          allFilters[option.name],
          (newValue) => updateFilter(option.name, newValue)
        )
      )}
    </>
  );
}

关键说明

  • 循环渲染时必须给每个Accordion添加唯一key(使用option.name即可),避免React警告
  • updateFilter函数利用计算属性名[filterKey]动态指定要更新的状态属性,确保灵活适配新增的筛选项
  • 初始状态通过reduce自动生成,后续新增options项时无需手动修改状态初始化代码

内容的提问来源于stack exchange,提问作者André Ricardo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 23:22:15