如何为React元素创建唯一键?

时间:2016-09-17 16:57:11

标签: reactjs

我正在创建一个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

14 个答案:

答案 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}>

修改

然而,正如用户Martin Dawson在下面的评论中指出的那样,这并不总是理想的。

那么解决方案是什么呢?

许多

  • 您可以创建一个函数来生成唯一键/ ids /数字/字符串并使用
  • 您可以使用现有的npm包,例如uuiduniqid
  • 您还可以生成 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> ) }); 之类的随机数字,并在其前面加上您要重复的项目,以保证其唯一性
  • 最后,我建议使用从数据库中获取的唯一ID,如果你得到它。

示例:

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 为孩子分配键

您可以利用 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 了解更多信息但总结一下:

  • 首先在你的终端和你的项目文件中:npm install uniqid
  • 在您的项目中导入 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()}>