No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Generador automático de IDs

21/30
Recursos

Aportes 24

Preguntas 2

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Yo lo que hice fue utilizar el método estático Date.now(), el cuál devuelve la cantidad de milisegundos transcurridos desde el primero de enero de 1970.


function newTodoId() {
  return Date.now();
}
//Devuelve el numero de milisegundos, ejemplo: 1668393426376

De esa forma, tenemos una id con un numero que nunca va a ser igual, a menos que registremos dos TODOs en el mismo milisegundo, lo que espero que para nuestro caso específico nunca suceda.

¡Hola, comuniadad! 👋

Yo utilicé la librería que viene instalada en node_modules llamada uuid.

✍ Nota: Las nuevas versiones tienen a dar inconveniente con la exportación por defecto, por eso le dejo la forma de solventar el error:

import { v4 as uuid } from 'uuid';

// Y luego, la variable que creamos llamada uuid, la necesitamos ejecutar como una función. 

const id = uuid();

🤙 Y listo, así es como se solventa y se puede utilizar esta librería que trae la carpeta node_modules.

Mi solución con generators:

  function* generateId() {
        let id = toDos.length
        while (true) {
            yield id++
        }
    }

    const newTodoId = generateId()

Yo use el metodo randomUUID(). Genera de manera aleatoria 36 digitos…
Dejo la info de MDN

function newTodoId(){
  return crypto.randomUUID()
}
//  ejemplo:  "36b8f84d-df4e-4d49-b662-bcde71a8764f

Hay un metodo nativo de JS para generar UUID’s unicos

https://developer.mozilla.org/en-US/docs/Web/API/Crypto/randomUUID

Generador automático de IDs

.
Para generar IDs automáticos se puede crear una un directorio helpers dentro de src. Dentro de helpers creamos un archivo idGenerator.js, ahí crearemos un generator creador de IDs únicos para nuestros TODOs.
.

function* idGenerator(lastId) {
  let id = lastId + 1;
  while (true) {
    yield id;
    id += 1;
  }
}

function newId(idList) {
  const lastId = idList.length ? Math.max(...idList) : 0;
  
  return idGenerator(lastId).next().value;
}

export { newId };

.
La función generator idGenerator recibe el último ID y le aumenta 1, dentro de un ciclo true se retorna el ID y se pausa la función idGenerator; asi que la siguiente vez que se lo llame con .next() esta función continuará desde ese punto en la que se la dejó, aumentando el id en 1 y volviéndose a repetir el ciclo.
.
Por otro lado, la función newId recibe una lista de IDs, de dicha lista recupera en lastId el ID con valor máximo si es que hubiera una lista, sino por defecto ese valor será 0. Luego se retorna al generador pasándole el lastId y llamando a .next().value que nos retornará el valor del ID. Finalmente, exportamos el newId.
.
En useTodos.js se deberá modificar la forma en la que manipulábamos los TODOs, puesto que ya no se identifican por el texto sino por IDs.
.

...
import { newId } from '../helpers/idGenerator';

function useTodos() {
  const {
    item: todos,
    saveItem: saveTodos,
    sincronizeItem: sincronizeTodos,
    loading,
    error,
  } = useLocalStorage('TODOS_V2', []);
  ...

  const addTodo = (text) => {
    const idList = todos.map(todo => todo.id);
    let id = newId(idList);
    const newTodos = [...todos];
    newTodos.push({
      completed: false,
      text,
      id,
    });
    saveTodos(newTodos);
  };

  const completeTodo = (id) => {
    const todoIndex = todos.findIndex(todo => todo.id === id);
    const newTodos = [...todos];
    newTodos[todoIndex].completed = true;
    saveTodos(newTodos);
  };

  const deleteTodo = (id) => {
    const todoIndex = todos.findIndex(todo => todo.id === id);
    const newTodos = [...todos];
    newTodos.splice(todoIndex, 1);
    saveTodos(newTodos);
  };
  ...
}

export { useTodos };

.
En primer lugar, para no tener conflictos con los TODOs que ya existían y manejaban el texto como identificador, vamos a cambiar la versión del key del localStorage de TODOS_V1 a TODOS_V2.
.
Ahora nuestras funciones para completar y eliminar TODOs van a recibir al id del TODO para identificarlo y realizar las acciones correspondientes.
.
El mayor cambio se ve reflejado en addTodo donde hacemos uso de la función newId que hemos importado. Primero obtenemos la lista de IDs de nuestra lista de TODOs, creamos un id por medio de newId pasándole la lista de IDs y finalmente creamos y guardamos el TODO asignandole el ID creado.
.
Por último solo queda modificar la manera en la que se renderizan los TODOs en el componente HomePage, pasándole el ID como key a cada TODO y los argumentos de las funciones de las render props onComplete y onDelete.
.

{todo => (
          <TodoItem
            key={todo.id}
            text={todo.text}
            completed={todo.completed}
            onEdit={() => console.log('Editar todo')}
            onComplete={() => completeTodo(todo.id)}
            onDelete={() => deleteTodo(todo.id)}
          />
        )}

Se puede usar el paquete uuid que viene por defecto cuando se descargan los paquetes de react y asi no es necesario crear una funcion

const addTodo = (text) => {
  const id = uuidv4();
  const newTodos = [...todos];
  newTodos.push({
    completed: false,
    text,
    id
  });
  saveTodos(newTodos);
};

yo solo le añadí un 0 a la función generadora de IDs

const newTodoId = (todos)=> {
  const ids = todos.map(e => e.id)
  return Math.max(0, ...ids)+1
}
una forma mas directa seria usar crypto.randomUUID() , compatible en la mayoría de los navegadores 93% , si quieren pruébenlo en la consola ![](https://static.platzi.com/media/user_upload/image-ca3183c0-6d88-4204-9986-bf922a9fcdf1.jpg)![](https://static.platzi.com/media/user_upload/image-21abd41e-96e6-4829-a42e-074531ccb74d.jpg)

Este es un ejemplo de generador de IDs con generators.
.

function* generatorId(id=0) {
    while(true) {
        yield ++id;
    }
}

const tasks = [{text: "t1", id: 1},{text: "t2", id: 2},{text: "t3", id: 3},{text: "t4", id: 4}];
const currentId = generatorId(tasks.length)
addTask("t5");
console.log(tasks)
addTask("t6");
console.log(tasks)

function addTask(text) {
    const id = currentId.next().value;
    tasks.push({text, id})
}

.
Principalmente, tenemos al generador que recibe un id desde el cual empezar a generar IDs únicos, y en caso de no recibir uno entonces será 0 por defecto. Esta función consta de un ciclo infinito y en cada iteración se pausa la función y se retorna el id ya incrementado en 1.
.
Si tenemos una lista de tareas como en el ejemplo, podemos crear un llamado al generador y guardarlo en currentId.
Aparte tenemos una función que recibe el texto del nuevo task, entonces generamos un id llamando al currentId.next().value y luego añadimos la nueva tarea a la lista de tareas.
.
Si quisiéramos ser más precisos podríamos buscar dentro de las tareas el ID mayor y de esa manera asegurarnos que generador nos generará ID únicos.
.

function* generatorId(id=0) {
    while(true) {
        yield ++id;
    }
}

const tasks = [{text: "t1", id: 1},{text: "t2", id: 2},{text: "t3", id: 3},{text: "t4", id: 4}];
const currentId = initializeGenerator()
addTask("t5");
console.log(tasks)
addTask("t6");
console.log(tasks)

function initializeGenerator() {
    return tasks.length > 0 
        ? generatorId([...tasks].sort((a, b) => b.id - a.id)[0].id)
        : generatorId()
}

function addTask(text) {
    const id = currentId.next().value;
    tasks.push({text, id})
}

.
En este caso se aumenta una función initializeGenerator que nos devuelve el generatorId que utiliza como argumento al mayor ID de la lista de tareas o se devuelve sin pasarle ningún argumento.
.
La forma de encontrar el ID mayor es ordenando una copia de la lista de mayor a menor según el ID, por lo que el primer elemento nos asegura que será la tarea con el ID mayor, y tomamos su ID.

osea lo correcto seria generar un id nuevo o si el id ya no existe entonces generar un id con cualquier número que sea diferente a los existentes aqui les dejo una parte de mi codigo osea la parte mas importante

    const ids = Object.keys(data.items)
          const idN = ids.map(item=>Number(item.replace('item-','')))
          let idNew = 0
          for (let i = 1; i < 200; i++) {
          const condition = idN.some(item=>item === i)
          if(!condition){
            idNew = i
            break
          }
          }

Hola papus y mamus, dejo el codigo de la clase en TypeScript, si tienen recomendaciones sera bien recibidas.

import { Dispatch, SetStateAction, useState } from "react";
import { useLocalStorege } from "./useLocalStorage";

export interface ITodo {
  text:string,
  completed:boolean,
  id: string
}

interface State {
  searchedTodos: ITodo[]
  completedTodos: number,
  totalTodos: number,
  searchValue: string,
  loading: boolean,
  error: boolean,
  openModal: boolean,
}

interface StateUpdaters {
  setSearchValue: Dispatch<SetStateAction<string>>
  addTodo: (v:string)=>void
  completeTodo: (v:string)=>void,
  deleteTodo: (v:string)=>void,
  setOpenModal: Dispatch<SetStateAction<boolean>>
  sincronizeTodos: ()=>void
}

const useTodos = (): { state: State, stateUpdaters: StateUpdaters } => {
  
  const {
    item: todos,
    saveItem: saveTodos,
    loading,
    error,
    sincronizeItem:  sincronizeTodos,
  } = useLocalStorege<ITodo[]>('TODOS_V2', []);

  const completedTodos:number = todos.filter(todo=>todo.completed).length;
  const totalTodos:number = todos.length;
  const [searchValue, setSearchValue] = useState<string>('');
  const [openModal, setOpenModal] = useState(false);

  const searchedTodos = todos.filter(todo=> todo.text.toLowerCase().includes(searchValue.toLowerCase()));

  const addTodo = (text:string) => {
    const id = crypto.randomUUID();
    const newTodos = [...todos]
    newTodos.push({
      text,
      completed: false,
      id
    })
    saveTodos(newTodos)
  }
  
  const completeTodo = (id: string) =>{
    const newTodos = todos.map(todo=>{
      if(todo.id === id) todo.completed = !todo.completed;
      return todo;
    })
    saveTodos(newTodos);
  }

  const deleteTodo = (text: string) => {
    const newTodos = todos.filter(todo=>todo.text !== text);
    saveTodos(newTodos);
  }

  const state = {
    searchedTodos,
    completedTodos,
    totalTodos,
    searchValue,
    loading,
    error,
    openModal,
  }

  const stateUpdaters = {
    addTodo,
    setSearchValue,
    completeTodo,
    deleteTodo,
    setOpenModal,
    sincronizeTodos,
  }

  return {
    state,
    stateUpdaters,
  }
}

export { useTodos }

Yo me apoyé de Math.random 👀👀

function newTodoID () {
  const characteresNum = 10
  const words = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
  const numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
  const getAllCharacters = words.concat(numbers)
  let result = ''
  for (let index = 0; index < characteresNum; index++) {
    const randomIndex = Math.floor(Math.random() * getAllCharacters.length)
    result += getAllCharacters[randomIndex]
  }
  return result
}

No sé si sea robusto mi manera de generar id, pero me funcionó…
Solo use el tamaño del arreglo como id

  const addTodo = text =>{
    //generando id
    const id = todos.length +1;
    const newTodos = [...todos];
    newTodos.unshift({
      completed: false,
      text,
      id,
    });
    saveTodos(newTodos);
  };

por si a alguien le interesa esta funcion genera el ID del tamaño que nos interese

Yo implementé

Math.random().toString(36).splice(2)

para generar los Id’s.

Como yo he resuelto en otros lenguajes el caso de obtener el máximo id, asumiendo que la lista siempre se incrementa en 1 simplemente uso .length para ver el mayor y ese seria el nuevo id que guardo en la lista y retorno.

const todoId = []
function newTodoId(){
  const id = todoId?.length
  todoId.push(id);
  return id;
}

Esta solución implica que si se borran todos igual los ids van a seguir en aumento. Aunque, esto en crecimiento es mucho almacenamiento ocupado para una lista de id, que rápidamente se me ocurre que puede servir si se quiere saber que id han sido eliminados para tener el registro del total de eliminaciones o incluso para ver si se pueden reutilizar en el futuro

Antes de ver tu solución, hice la mía. Es menos legible y más robusta, pero funciona 👌

let greaterId = todoList.reduce((previousTodo, currentTodo) => {
      return (previousTodo.id > currentTodo.id) ? previousTodo.id : currentTodo.id;
   }, 0);
   return greaterId + 1;
Yo use un generador jeje *const* todoIdGenerator = useRef(idGenerator()); *function*\* idGenerator() { *let* id = parseInt(localStorage.getItem('nextId'), 10) || 1 *while* (*true*) { localStorage.setItem('nextId', JSON.stringify(id + 1)); *yield* id++; } } *const* handleOnCreateTodo = (e, text) => { e.preventDefault(); *const* newTodos = \[ { id: todoIdGenerator.current.next().value, text, completed: *false* ** }, ...todos, ]; setTodos(newTodos); setNewTodoValue(''); createTodoButton.click() todoFilterActionAll.click() }
Me pareció más random este generador ```js function generateRandomId() { const randomString = Math.random().toString(36).substring(2, 11); return randomString; } ```function generateRandomId() { const randomString = *Math*.random().toString(36).substring(2, 11); return randomString;}

Para generar los IDs unicos yo use una libreria llamada uuid

https://www.npmjs.com/package/uuid

en mi consola null+1 es igual a 1 XD

A mi me pinto la compleja y agarre data que lei en los comentarios y arme uno combinando un generador de ids en forma de string con el de Date.now(), los sume y multiplique x2 y cree esto.

function newTodoId() {
  const id = Date.now()
  
  const  generateRandomString = (num) => {
    let result1= Math.random().toString(36).substring(0, num);       

    return result1;
  }

  return generateRandomString(12) + id;
}
function generateId(array) {
  return (array.length)?(Math.max(...array.map(el=>el.id))+1):1
}