React中使用datalist出现Maximum Call Stack Size Exceeded错误,如何排查?
排查React渲染大量
<option>触发调用栈溢出的问题 核心诱因
你从FDA API拉取了38647条药品名称,直接全部渲染到<datalist>里,这会触发React递归渲染虚拟DOM时超出JavaScript调用栈的限制——JavaScript的调用栈深度有限,几万级别的子元素递归遍历必然撑爆栈。
排查步骤
- 确认数据量级:查看
console.log(drugs)的输出长度,你这里明确是3万+,这就是问题根源。 - 缩小数据测试:临时把API的
limit改成100,重新运行组件,如果不再报错,就实锤是大量DOM元素导致的渲染栈问题。 - 排除无限重渲染:检查
useEffect依赖项是空数组,只会触发一次setData;再确认data没有在渲染过程中被意外修改,排除无限重渲染的可能。
解决办法
1. 搜索过滤+限制渲染数量(最优方案)
原生<datalist>本来就不适合处理超大量数据,直接根据输入值过滤结果,只渲染匹配的前几十条:
const { useState, useEffect } = React function App() { const [data, setData] = useState([]) const [searchVal, setSearchVal] = useState('') const [filteredDrugs, setFilteredDrugs] = useState([]) useEffect(() => { fetch('https://api.fda.gov/drug/label.json?count=openfda.brand_name.exact&limit=38647') .then(res => res.json()) .then(json => { const drugs = json.results.map(i => i.term) setData(drugs) }) .catch(err => console.error(err)) }, []) // 根据输入过滤药品,只取前100条 useEffect(() => { if (!searchVal) { setFilteredDrugs([]) return } const matches = data.filter(drug => drug.toLowerCase().includes(searchVal.toLowerCase()) ).slice(0, 100) setFilteredDrugs(matches) }, [searchVal, data]) return ( <div> <input list='drugs' value={searchVal} onChange={e => setSearchVal(e.target.value)} /> <datalist id='drugs'> {filteredDrugs.map((drug, index) => ( <option value={drug} key={`drug-${drug}-${index}`} /> ))} </datalist> </div> ) } ReactDOM.createRoot(document.getElementById("root")).render(<App/>)
2. 检查并修复重复key
如果API返回的term有重复值,React的key冲突会加重渲染异常,给key加上索引兜底:
<option value={i} key={`drug-${i}-${index}`} />
3. 避免全量渲染
不要尝试一次性渲染3万+<option>,哪怕优化React渲染逻辑,浏览器也会因为DOM节点过多出现假死,搜索过滤才是合理的做法。
内容的提问来源于stack exchange,提问作者Joy
相关产品推荐
相关产品推荐

