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

React如何基于对象数组动态生成带对应参数的下拉选择框与提交按钮

核心原因是单个字符串状态只能存储一个下拉的选中值,多投票项场景下会出现状态互相覆盖的问题,以下是两种成熟的实现方案:

解决方案

方案1:拆分为独立子组件(推荐,逻辑更清晰)

把单个投票项的逻辑抽成单独的PollItem组件,每个组件自己维护内部的选中状态,和你之前写的单条逻辑完全一致,不会互相干扰。

子组件代码:

// 先定义子组件的入参类型
interface PollItemProps {
  title: string;
  optionsStr: string; // 对应原poll里的options字段,是分号分隔的字符串
  returnAddress: string;
  onSend: (returnAddress: string, selectedOption: string) => void;
}

const PollItem = ({ title, optionsStr, returnAddress, onSend }: PollItemProps) => {
  // 每个子组件自己的选中状态,互相独立
  const [selectedOption, setSelectedOption] = useState('');
  // 拆分分号分隔的选项
  const options = optionsStr.split(';');

  const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
    setSelectedOption(e.target.value);
  };

  const handleClick = () => {
    if (selectedOption) {
      onSend(returnAddress, selectedOption);
    }
  };

  return (
    <div className="poll-item">
      <h3>{title}</h3>
      <select value={selectedOption} onChange={handleChange}>
        <option value="">请选择选项</option>
        {options.map(opt => (
          <option key={opt} value={opt}>{opt}</option>
        ))}
      </select>
      <button onClick={handleClick} disabled={!selectedOption}>提交</button>
    </div>
  )
}

父组件使用:

// 父组件里直接遍历polls数组渲染子组件即可
const Parent = () => {
  // 你原来的polls数组,这里修正了对象属性的语法错误(将=替换为:)
  const polls = [
    {
      title: "poll1",
      options: "option1;option2;option3",
      returnAddress: "xYn38akn[...]"
    },
    {
      title: "poll2",
      options: "optionA;optionB;optionC",
      returnAddress: "nJb3enH[...]"
    },
  ]

  // 你原来的onSend方法
  const onSend = (returnAddress: string, selectedOption: string) => {
    // 原有业务逻辑
    console.log(returnAddress, selectedOption)
  }

  return (
    <div className="poll-list">
      {polls.map(poll => (
        <PollItem 
          key={poll.returnAddress} // 用全局唯一的returnAddress当key
          title={poll.title}
          optionsStr={poll.options}
          returnAddress={poll.returnAddress}
          onSend={onSend}
        />
      ))}
    </div>
  )
}

方案2:父组件用对象存储所有选中值

如果你不想拆分组件,可以把state改为对象结构,用每个poll的唯一标识(比如returnAddress)作为key存储对应选中值:

const Parent = () => {
  const polls = [/* 你的原有polls数组 */]
  // 状态改为对象,key是returnAddress,value是对应poll的选中选项
  const [selectedMap, setSelectedMap] = useState<Record<string, string>>({})

  const handleChange = (returnAddress: string, e: React.ChangeEvent<HTMLSelectElement>) => {
    setSelectedMap(prev => ({
      ...prev,
      [returnAddress]: e.target.value
    }))
  }

  const handleSend = (returnAddress: string) => {
    const selectedOption = selectedMap[returnAddress]
    if (selectedOption) {
      onSend(returnAddress, selectedOption)
    }
  }

  return (
    <div className="poll-list">
      {polls.map(poll => {
        const options = poll.options.split(';')
        const selected = selectedMap[poll.returnAddress] || ''
        return (
          <div key={poll.returnAddress}>
            <h3>{poll.title}</h3>
            <select 
              value={selected} 
              onChange={(e) => handleChange(poll.returnAddress, e)}
            >
              <option value="">请选择选项</option>
              {options.map(opt => <option key={opt} value={opt}>{opt}</option>)}
            </select>
            <button onClick={() => handleSend(poll.returnAddress)} disabled={!selected}>
              提交
            </button>
          </div>
        )
      })}
    </div>
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 01:15:03