我正在创建一个React应用程序,允许您创建一个列表并保存它,但React一直在警告我,我的元素没有唯一的关键道具(元素List / ListForm)。我应该如何为用户创建的元素创建唯一的关键道具?以下是我的React代码
lazy var startTimer : Timer = {
return Timer.scheduledTimer(timeInterval: 4.0, target: self, selector: #selector(update), userInfo: nil, repeats: false)
}()
我的HTML:
let _ = startTimer
答案 0 :(得分:28)
您可以通过多种方式创建unique keys
,最简单的方法是在迭代数组时使用索引。
实施例
var lists = this.state.lists.map(function(list, index) {
return(
<div key={index}>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
只要您在this.state.lists.map
点击数据,您就可以将第二个参数 function(list, index)
传递给回调,这将是{{1}值,它对于数组中的所有项都是唯一的。
然后你可以像
一样使用它 index
你也可以在这里做同样的事情
<div key={index}>
那么解决方案是什么呢?
许多
var savedLists = this.state.savedLists.map(function(list, index) {
var list_data = list.data;
list_data.map(function(data, index) {
return (
<li key={index}>{data}</li>
)
});
return(
<div key={index}>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
之类的随机数字,并在其前面加上您要重复的项目,以保证其唯一性示例:
new Date().getTime();
答案 1 :(得分:9)
一个人可以使用uuid
npm软件包。
Nodejs通用模块
const uuidv1 = require('uuid/v1');
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
使用ecma6:
import uuidv1 from 'uuid/v1';
uuidv1(); // '10ba038e-48da-487b-96e8-8d3b99b6d18a
答案 2 :(得分:8)
如https://docs.ruby-lang.org/en/2.0.0/Net/HTTP.html#method-c-get_response所述,不建议对键“ 使用索引,如果项目的顺序可能更改。这可能会对性能产生负面影响,并可能导致组件状态出现问题”。在这种情况下,我建议使用名为 react documentation 的工具。
1)使用NPM / YARN安装软件包:
npm install shortid --save
2)导入要使用的类文件:
import shortid from 'shortid';
2)生成新ID的命令是 shortid.generate()。
3)示例:
renderDropdownItems = (): React.ReactNode => {
const { data, isDisabled } = this.props;
const { selectedValue } = this.state;
const dropdownItems: Array<React.ReactNode> = [];
if (data) {
data.forEach(item => {
dropdownItems.push(
<option value={item.value} key={shortid.generate()}>
{item.text}
</option>
);
});
}
return (
<select
value={selectedValue}
onChange={this.onSelectedItemChanged}
disabled={isDisabled}
>
{dropdownItems}
</select>
);
};
希望这会有所帮助。我刚刚发布了这篇文章,因为很难找到这样的解决方案。
答案 3 :(得分:5)
重要的是要记住,React期望使用 STABLE 键,这意味着您应该分配一次键,并且列表中的每个项目每次都应收到相同的键,这样React可以围绕数据进行优化在调整虚拟DOM时会更改,并确定需要重新呈现的组件。 因此,如果您正在使用UUID,则需要在数据级别而不是UI级别进行操作。
还请记住,您可以使用任意字符串作为键,因此您通常可以将多个字段组合成一个唯一的ID,例如characterEncoding=UTF-8
可能是聊天中一行的唯一键,例如。
答案 4 :(得分:4)
请勿使用此return
$ {pre __ $ {new Date()。getTime()} ;
。最好使用数组索引而不是数组索引,因为即使它不理想,那样的话,至少也可以使列表组件之间保持一定的一致性,而使用新的新Date函数,您将获得恒定的不一致。这意味着该函数的每次新迭代都将导致一个新的真正唯一的键。
唯一键并不意味着它必须是全局唯一的,它意味着它在组件的上下文中必须是唯一的,因此它不会一直无用地重新渲染。您最初不会感觉到与新Date相关的问题,但是会感觉到它,例如,如果您需要返回到已渲染的列表并且React开始感到困惑,因为它不知道哪个组件发生了更改以及哪个组件发生了更改否则,会导致内存泄漏,因为根据您的Date键,您猜到了每个组件都发生了更改。
现在我的答案。假设您要渲染一个YouTube视频列表。使用视频ID(arqTu9Ay4Ig)作为唯一ID。这样,如果该ID不变,则该组件将保持不变,但是如果保持不变,React将识别出它是一个新视频,并相应地对其进行更改。
不必那么严格,稍微放松一点的变体就是使用标题,例如Erez Hochman已经指出的那样,或者使用组件属性的组合(标题加类别),这样您就可以知道反应检查它们是否已更改。
编辑了一些不重要的内容
答案 5 :(得分:2)
使用V4的UUID更新答案
GameRootNode = SCNNode()
let Sequence = SCNAction.sequence([SCNAction.scale(to: VCOfScene.VCPlayAR.ScalingFactor, duration: 0),
SCNAction.move(to: SCNVector3.init(-Float(kNbColonnesLevel) / 2 * Float(VCOfScene.VCPlayAR.ScalingFactor),
0,
-Float(kNbLignesLevel) / 2 * Float(VCOfScene.VCPlayAR.ScalingFactor)),
duration: 0)])
GameRootNode.runAction(Sequence)
BulletNode = SCNNode(geometry: Level3D.Bullet.geometry)
BulletNode.position = Position.PositionToVector()
BulletNode.name = ProjectileImageName + String(ProjectileID)
let BulletShape = SCNParticleSystem(named: "Fireball.scnp", inDirectory: nil)!
BulletShape.emittingDirection = DirectionBullet
BulletShape.particleColor = Character.Color
BulletNode.addParticleSystem(BulletShape)
GameRootNode.addChildNode(BulletNode)
GameRootNode.runAction(Sequence)
答案 6 :(得分:1)
您可以利用 React.Children API:
const { Children } = React;
const DATA = [
'foo',
'bar',
'baz',
];
const MyComponent = () => (
<div>
{Children.toArray(DATA.map(data => <p>{data}</p>))}
</div>
);
ReactDOM.render(<MyComponent />,document.getElementById("root"));
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
答案 7 :(得分:0)
const randomId = Math.round(Math.random() * 100000000)
想要的越随机,就越容易增加乘数。
但最好使用一些可信任的库来生成随机ID。
答案 8 :(得分:0)
要添加 2021 年的最新解决方案...
我发现项目 nanoid 提供了可用作键的唯一字符串 ID,同时速度快且体积小。
使用npm install nanoid
安装后,使用如下:
import { nanoid } from 'nanoid';
// Have the id associated with the data.
const todos = [{id: nanoid(), text: 'first todo'}];
// Then later, it can be rendered using a stable id as the key.
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
)
答案 9 :(得分:0)
另一个选项是弱密钥:https://www.npmjs.com/package/weak-key
import weakKey from "weak-key";
const obj1 = {a : 42};
const obj2 = {b : 123};
const obj3 = {a : 42};
console.log(weakKey(obj1)); // 'weak-key-1'
console.log(weakKey(obj2)); // 'weak-key-2'
console.log(weakKey(obj3)); // 'weak-key-3'
console.log(weakKey(obj1)); // 'weak-key-1'
答案 10 :(得分:-1)
您可以使用 react-html-id 轻松生成uniq ID:https://www.npmjs.com/package/react-html-id
答案 11 :(得分:-1)
import React, {useState} from 'react';
import {SafeAreaView,ScrollView,StyleSheet,Text,View,Dimensions} from 'react-native';
const {width}=Dimensions.get('window');
function sayfalar(){
let pages=[]
for (let i = 0; i < 100; i++) {
pages.push(<View key={i} style={styles.pages}><Text>{i}</Text></View>)
}
return pages
}
const App=()=>{
return(
<View style={styles.container}>
<ScrollView horizontal={true} pagingEnabled={true}>
{sayfalar()}
</ScrollView>
</View>
)
}
const styles = StyleSheet.create({
container:{
flexDirection:'row',
flex:1
},
pages:{
width:width
}
})
export default App;
答案 12 :(得分:-1)
2021 年最快的解决方案是使用 uniqid:转到 https://www.npmjs.com/package/uniqid 了解更多信息但总结一下:
uniqid = require('uniqid');
return(
<div>
<div key={ uniqid() } id={list.name}>
<h2 key={ uniqid() }>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
答案 13 :(得分:-7)
我正在使用这个:
<div key={+new Date() + Math.random()}>