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

