我有一个向购物车添加商品的函数。当一个按钮被点击时,我试图为一个新的对象项生成一个唯一的键。我让new Date().getTime()根据点击频率做这件事。我在函数内部测试了console.log,它为每个新对象生成不同的unique_id编号。当我尝试将现有的对象状态数组与新的item对象组合在一起时,问题就开始了。所有现有的unique_id都会被覆盖到最新的unique_id。我还对状态数组使用了React useState钩子。React在某种程度上是相关的,因为不应该直接编辑状态数组,而是通过setter方法进行编辑。
我尝试了.push、.concat、Array.from、扩展运算符、循环和在函数内部和外部赋值变量的组合。我知道这是pass-by-reference和pass-by-value的情况,因为那些数组方法只是浅层拷贝。
const [cart, setCart] = useState([])
const addItem = (item) => {
let cartArr = cart
item['unique_id'] = new Date().getTime()
setCart([...cartArr, item])
}期望值:
[
{id: 1, price: 10.11, title: "The Art Of War", unique_id: 1565675696123},
{id: 1, price: 10.11, title: "The Art Of War", unique_id: 1565675696256},
{id: 1, price: 10.11, title: "The Art Of War", unique_id: 1565675696377}
]但得到的是:
[
{id: 1, price: 10.11, title: "The Art Of War", unique_id: 1565675696377},
{id: 1, price: 10.11, title: "The Art Of War", unique_id: 1565675696377},
{id: 1, price: 10.11, title: "The Art Of War", unique_id: 1565675696377}
]发布于 2019-08-13 14:51:45
您可以将数组和对象连接起来,而不是将值推入数组中,请参阅下面的代码以供参考
const [cart, setCart] = useState([]);
const addItem = item => {
item["unique_id"] = new Date().getTime();
setCart([...cart, item]);
};发布于 2019-08-13 14:33:45
正如我在评论中提到的,这取决于您调用addItem的频率。下面的代码片段显示,如果您连续调用addItem,则所有项都会获得相同的时间(几乎总是):
let cart = [];
const addItem = (item) => {
let cartArr = cart;
let currentTime = new Date().getTime();
item['unique_id'] = currentTime;
cartArr.push(item);
cart = cartArr;
}
addItem({ price: 10 });
addItem({ price: 11 });
addItem({ price: 12 });
console.log(cart);
但是,在通过引入console.log添加一些延迟之后,时间戳是不同的(不能保证):
let cart = [];
const addItem = (item) => {
let cartArr = cart;
let currentTime = new Date().getTime();
console.log('Price: ' + item.price);
console.log('Current time: ' + currentTime);
item['unique_id'] = currentTime;
cartArr.push(item);
cart = cartArr;
}
addItem({ price: 10 });
addItem({ price: 11 });
addItem({ price: 12 });
console.log(cart);
所以,在这里,我认为React状态与时间戳或数组操作无关。
发布于 2019-08-13 15:02:04
正如@fiveelements所说,由于Date.now()不是一种可靠的生成随机值的方法,因此您会遇到ids冲突。幸运的是,浏览器有一个生成随机值的新功能。您可以尝试将以下内容用于您的ids:
const id = window.crypto.getRandomValues(new Uint32Array(10))[0];
console.log(id);
您可以阅读有关window.crypto object on MDN的更多信息。包括IE11:https://caniuse.com/#search=crypto在内的所有现代浏览器都支持它。
如果您从数据库之类的地方获得数据,那么您可能已经有了某种可以使用的唯一id。如果可以在渲染之间保持key的一致性,则可以通过避免不必要的重新渲染来提高性能。但是,如果您没有任何id,这个代码片段可以帮助您动态生成它们。
您还可以检查此CodePen。
https://stackoverflow.com/questions/57471938
复制相似问题