React新手遇`key`非props警告问题求助
React
key 非Props警告的解决办法 问题概述
开发React购物车项目时,控制台持续弹出如下警告:
react-jsx-dev-runtime.development.js:87 Warning: CartItem: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://reactjs.org/link/special-props) at CartItem (http://localhost:3000/static/js/bundle.js:206:5) at div at div at Cart (http://localhost:3000/static/js/bundle.js:390:5) at header at div at App
先后尝试将item.id、map的index作为key值,警告仍未消失,但相同代码放到codesandbox中无此问题。本地完整代码如下:
App.js
import logo from './logo.svg'; import Cart from './cart'; import './App.css'; const cartItems = [ {id:1,name:"Pepperoni Pizza", price: 5.50, qty:1}, {id:2,name:"Ham & Cheese Pizza", price: 6.00, qty:5}, {id:3,name:"Supreme Pizza", price: 9.00, qty:3} ] function App() { return ( <div className="App"> <header className="App-header"> <Cart baseItems={cartItems}/> </header> </div> ); } export default App;
Cart.js
import React, { useState, useEffect } from 'react'; import "./Cart.css" import CartItem from './CartItem'; function Cart({ baseItems }) { const initState = JSON.parse(window.localStorage.getItem('items')); const [items, setItems] = useState(initState || baseItems) const cartTotal = baseItems.reduce( (total, item) => ( total + item.qty * item.price ), 0 ).toFixed(2) const updateQty = (id, updatedQty) => { const newItems = items.map(item => { if (item.id === id) { return { ...item, qty: updatedQty } } return item; }) setItems(newItems); } useEffect(() => { window.localStorage.setItem('items', JSON.stringify(items)) }, [items]); return ( <div className="Cart"> <h1 className="Cart-Title"> Shopping Cart</h1> <div className="Cart-Items"> {items.map((item, index) => { return <CartItem key={index} updateItemQuantity={updateQty} {...item} /> })} </div> <h2 className="Cart-Total"> Total = ${cartTotal} </h2> </div> ); } export default Cart;
CartItem.js
import React from 'react'; import "./CartItem.css" function CartItem({name, price, id, qty,updateItemQuantity }) { const AddAmt = (amt) => { updateItemQuantity(id,qty+amt) } return ( <div className="Cart-Item"> <div>{name}</div> <div>${price}</div> <div> <button onClick={() =>AddAmt(-1)} disabled={qty <= 1}>-</button> {qty} <button onClick={() => AddAmt(1)}>+</button> </div> <div>Total = ${qty*price}</div> </div> ); } export default CartItem;
解决思路与步骤
1. 警告根源
React的key是内部专用属性,不会被当作props传递给子组件。当前代码里没有直接读取props.key,警告出现的原因可能是:
- 本地开发环境的React版本与codesandbox存在差异,旧版本的开发模式检查更严格;
- 本地存在代码缓存(比如之前的
CartItem尝试读取过key,未彻底清理); - 开发服务器热更新残留了旧逻辑。
2. 具体修复方案
- 使用稳定的
key值:放弃用index作为key(列表项增删或排序时会引发不必要的重渲染),改用item.id,这是React官方推荐的列表项key设置方式:// 修改Cart.js中的map渲染代码 {items.map((item) => { return <CartItem key={item.id} updateItemQuantity={updateQty} {...item} /> })} - 清理缓存并重启服务:关闭本地开发服务器,删除项目的
node_modules/.cache目录(如果是Create React App项目),同时清空浏览器缓存,再重新启动服务; - 对齐依赖版本:查看codesandbox中的React版本,将本地项目的React、React-dom版本更新为一致,避免版本差异导致的检查逻辑不同。
3. Codesandbox无警告的原因
Codesandbox默认使用的React版本可能调整了开发模式的警告策略,或者该版本中针对此类场景的检查逻辑更宽松。但无论线上环境是否报警,都应该遵循React的规范编写代码。
额外优化建议
- 购物车总价计算应使用状态中的
items而非baseItems,否则修改数量后总价不会同步更新:const cartTotal = items.reduce( (total, item) => total + item.qty * item.price, 0 ).toFixed(2) - 若子组件需要用到
key对应的数值(比如这里的item.id),需单独传递props,不要尝试读取props.key。
内容的提问来源于stack exchange,提问作者ryan112
相关产品推荐
相关产品推荐

