reactjs - page - react meta tags
¿Cómo crear claves únicas para reactivar elementos? (9)
Actualizando la respuesta con v4 de UUID.
npm install uuid
-------------------------------------
const uuidv4 = require(''uuid/v4'');
uuidv4(); // ⇨ ''10ba038e-48da-487b-96e8-8d3b99b6d18a''
or
import uuidv from ''uuid/v4'';
uuidv4(); // ''10ba038e-48da-487b-96e8-8d3b99b6d18a
Estoy creando una aplicación React que te permite hacer una lista y guardarla, pero React me ha advertido que mis elementos no tienen una propiedad clave única (elementos List / ListForm). ¿Cómo debo crear una clave única para los elementos creados por el usuario? A continuación se muestra mi código React
var TitleForm = React.createClass({
handleSubmit: function(e) {
e.preventDefault();
var listName = {''name'':this.refs.listName.value};
this.props.handleCreate(listName);
this.refs.listName.value = "";
},
render: function() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<input className=''form-control list-input'' type=''text'' ref=''listName'' placeholder="List Name"/>
<br/>
<button className="btn btn-primary" type="submit">Create</button>
</form>
</div>
);
}
});
var ListForm = React.createClass({
getInitialState: function() {
return {items:[{''name'':''item1''}],itemCount:1};
},
handleSubmit: function(e) {
e.preventDefault();
var list = {''name'': this.props.name, ''data'':[]};
var items = this.state.items;
for (var i = 1; i < items.length; i++) {
list.data.push(this.refs[items[i].name]);
}
this.props.update(list);
$(''#''+this.props.name).remove();
},
handleClick: function() {
this.setState({
items: this.state.items.concat({''name'':''item''+this.state.itemCount+1}),
itemCount: this.state.itemCount+1
});
},
handleDelete: function() {
this.setState({
itemCount: this.state.itemCount-1
});
},
render: function() {
var listItems = this.state.items.map(function(item) {
return (
<div>
<input type="text" className="list-form" placeholder="List Item" ref={item.name}/>
<br/>
</div>
);
});
return (
<div>
<form onSubmit={this.handleSubmit} className="well list-form-container">
{listItems}
<br/>
<div onClick={this.handleClick} className="btn btn-primary list-button">Add</div>
<div onClick={this.handleDelete} className="btn btn-primary list-button">Delete</div>
<button type="submit" className="btn btn-primary list-button">Save</button>
</form>
</div>
)
}
});
var List = React.createClass({
getInitialState: function() {
return {lists:[], savedLists: []};
},
handleCreate: function(listName) {
this.setState({
lists: this.state.lists.concat(listName)
});
},
updateSaved: function(list) {
this.setState({
savedLists: this.state.savedLists.concat(list)
});
},
render: function() {
var lst = this;
var lists = this.state.lists.map(function(list) {
return(
<div>
<div key={list.name} id={list.name}>
<h2 key={"header"+list.name}>{list.name}</h2>
<ListForm update={lst.updateSaved} name={list.name}/>
</div>
</div>
)
});
var savedLists = this.state.savedLists.map(function(list) {
var list_data = list.data;
list_data.map(function(data) {
return (
<li>{data}</li>
)
});
return(
<div>
<h2>{list.name}</h2>
<ul>
{list_data}
</ul>
</div>
)
});
var save_msg;
if(savedLists.length == 0){
save_msg = ''No Saved Lists'';
}else{
save_msg = ''Saved Lists'';
}
return (
<div>
<TitleForm handleCreate={this.handleCreate} />
{lists}
<h2>{save_msg}</h2>
{savedLists}
</div>
)
}
});
ReactDOM.render(<List/>,document.getElementById(''app''));
Mi HTML:
<div class="container">
<h1>Title</h1>
<div id="app" class="center"></div>
</div>
Como explica la documentación de reacción , no se recomienda usar el índice para las claves " si el orden de los elementos puede cambiar. Esto puede afectar negativamente el rendimiento y puede causar problemas con el estado del componente ". En este caso, recomiendo usar una herramienta que se llama shortid .
1) Instale el paquete usando NPM / YARN:
npm install shortid --save
2) Importa en el archivo de clase que quieras usarlo:
import shortid from ''shortid'';
2) El comando para generar una nueva identificación es shortid.generate () .
3) Ejemplo :
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>
);
};
Espero que esto ayude. Acabo de publicar esto porque fue muy difícil encontrar una solución como esta.
Es importante recordar que React espera las teclas ESTABLES , lo que significa que debe asignar las teclas una vez, y cada elemento de su lista debe recibir la misma clave cada vez, de esa manera, React puede optimizar sus cambios de datos cuando concilia el DOM virtual y decide qué componentes deben volver a renderizarse. Por lo tanto, si está utilizando UUID, debe hacerlo a nivel de datos, no a nivel de interfaz de usuario.
También tenga en cuenta que puede usar cualquier cadena que desee para la clave, por lo que a menudo puede combinar varios campos en una ID única, algo así como ${username}_${timestamp}
puede ser una clave única fina para una línea en un chat , por ejemplo.
Estoy usando esto:
<div key={+new Date() + Math.random()}>
Hay muchas formas en las que puede crear unique keys
; el método más simple es utilizar el índice al iterar matrices.
Ejemplo
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>
)
});
Donde quiera que esté saltando sobre los datos, aquí this.state.lists.map
, también puede pasar la segunda function(list, index)
parámetro function(list, index)
a la devolución de llamada y ese será su valor de index
y será único para todos los elementos en la matriz.
Y luego puedes usarlo como
<div key={index}>
Puedes hacer lo mismo aquí también.
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>
)
});
Editar
Sin embargo, como señaló el usuario Martin Dawson en el comentario a continuación, esto no siempre es ideal.
Entonces, ¿cuál es la solución?
Muchos
- Puede crear una función para generar claves / ID / números / cadenas únicas y usar esa
- Puede utilizar paquetes npm existentes como uniqid , uniqid , etc.
- También puede generar un número aleatorio como
new Date().getTime();
y el prefijo con algo del elemento que está iterando para garantizar su singularidad - Por último, recomiendo usar la ID única que obtiene de la base de datos, si la obtiene.
Ejemplo:
const generateKey = (pre) => {
return `${ pre }_${ new Date().getTime() }`;
}
const savedLists = this.state.savedLists.map( list => {
const list_data = list.data.map( data => <li key={ generateKey(data) }>{ data }</li> );
return(
<div key={ generateKey(list.name) }>
<h2>{ list.name }</h2>
<ul>
{ list_data }
</ul>
</div>
)
});
No use esta return
$ {pre} _ $ {nueva Fecha (). GetTime ()} ;
. Es mejor tener el índice de matriz en lugar de eso, porque, aunque no es lo ideal, de esa manera al menos obtendrá cierta coherencia entre los componentes de la lista, con la nueva función de fecha obtendrá una inconsistencia constante. Eso significa que cada nueva iteración de la función llevará a una nueva clave verdaderamente única.
La clave única no significa que deba ser globalmente única, significa que debe ser única en el contexto del componente, por lo que no se ejecuta ininterrumpidamente las representaciones. No sentirá el problema asociado con la nueva Fecha inicialmente, pero lo sentirá, por ejemplo, si necesita volver a la lista ya procesada y React comienza a confundirse porque no sabe qué componente cambió y cuál no lo hizo, lo que provocó pérdidas de memoria, ya que, según su clave de fecha, todos los componentes cambiaron.
Ahora a mi respuesta. Digamos que estás mostrando una lista de videos de YouTube. Utilice la ID de video (arqTu9Ay4Ig) como ID única. De esa manera, si esa identificación no cambia, el componente seguirá siendo el mismo, pero si lo hace, React reconocerá que es un nuevo video y lo cambiará en consecuencia.
No tiene que ser tan estricto, la variante poco más relajada es usar el título, como Erez Hochman ya mencionó, o una combinación de los atributos del componente (título más categoría), por lo que puede decirle a React que verifique Si han cambiado o no.
editado algunas cosas sin importancia
Puede usar react-html-id para generar uniq id fácilmente: https://www.npmjs.com/package/react-html-id
Se puede usar el paquete uuid npm para ello.
Módulo común de Nodejs
const uuidv1 = require(''uuid/v1'');
uuidv1(); // ''10ba038e-48da-487b-96e8-8d3b99b6d18a
Con ecma6:
import uuidv1 from ''uuid/v1'';
uuidv1(); // ''10ba038e-48da-487b-96e8-8d3b99b6d18a
Una de las formas más rápidas y sencillas que uso personalmente es usar Math.random()
junto con los valores del mapa (itemName, index)
manera:
<div key={itemName + index + Math.random()} ..... >