React中基于复选框开关增删state项及解决key警告方法
问题根因
- 现有逻辑在同一个
useEffect内连续触发多次setProducts,每次更新都基于上一次的临时状态做增删,当两个复选框状态同时变化时,会重复添加商品,导致作为key的商品title重复,触发React key警告。 products是复选框状态的派生值,完全不需要单独维护状态、也不需要用useEffect监听修改,直接根据当前勾选状态计算即可,从根源避免状态不同步问题。
修复后完整代码
const root = ReactDOM.createRoot(document.getElementById("root")) const initialArray = [ { title: "Belts", for: "men" }, { title: "Makeup", for: "women" } ]; function App() { const [menToggle, setMenToggle] = React.useState(false); const [womenToggle, setWomenToggle] = React.useState(false); // 直接根据勾选状态筛选要展示的商品,无需额外维护products状态 const products = initialArray.filter(item => { if (item.for === "men") return menToggle; if (item.for === "women") return womenToggle; return false; }); return ( <div className="App"> <label> <input type="checkbox" checked={menToggle} onChange={() => setMenToggle((prevValue) => !prevValue)} /> 男士 </label> <label> <input type="checkbox" checked={womenToggle} onChange={() => setWomenToggle((prevValue) => !prevValue)} /> 女士 </label> <ul> {products.map((item) => <li key={item.title}>{item.title}</li>)} </ul> </div> ); } root.render(<App />);
对应的HTML入口代码:
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script> <div id="root"></div>
核心修改点
- 移除冗余的
products状态和对应的useEffect更新逻辑,彻底解决多次调用setState导致的重复数据问题 - 直接通过数组
filter方法从源商品数据中筛选符合当前勾选规则的商品,逻辑简洁,不会出现状态不一致 - 将商品列表外层容器从
div替换为语义化的ul标签,符合HTML规范(li标签需要作为ul/ol的子元素) - 删除多余的非空判断:空数组调用
map不会抛出错误,会直接返回空内容,不需要额外判断products存在且长度大于0
内容的提问来源于stack exchange,提问作者Whiz
相关产品推荐
相关产品推荐

