Skip to content

Instantly share code, notes, and snippets.

@jul-sh
Last active February 11, 2020 11:14
Show Gist options
  • Save jul-sh/5ba21f7698aa87ab56081092aef6d3a4 to your computer and use it in GitHub Desktop.
Save jul-sh/5ba21f7698aa87ab56081092aef6d3a4 to your computer and use it in GitHub Desktop.
The goal of this hook is to provide an alternative to using indexes as keys in react. Instead, what if we could use the object references as keys. Since React only accepts strings as keys, let's associate string keys to object references.
import React from 'react'
import { render } from 'react-dom'
/*
The goal of this hook is to provide an alternative to using indexes as
keys in react. Instead, what if we could use the object references as keys.
Since React only accepts strings as keys, let's associate string keys to
object references.
*/
function useObjectToKey() {
let iterator = 0
const { current: keysByObject } = React.useRef(new WeakMap())
function objectToKey(object) {
// If we already genereated a key for this object,
// we return it.
if (keysByObject.has(object)) {
return keysByObject.get(object)
}
// If we have not stored a string key for this object yet,
// we'll create one.
const genereatedId = iterator.toString()
// And store it, associated to this object
keysByObject.set(object, genereatedId)
// Lastly we should incement our iterator, so that the
// the next generated key is different to the one we just
// created.
iterator = iterator + 1
// Finally we can return this key
return genereatedId
}
return objectToKey
}
function GroceryList() {
const objectToKey = useObjectToKey()
const [groceries, setGroceries] = React.useState([
{ name: 'Soy Milk', quantity: 1 },
{ name: 'Bread', quantity: 2 },
{ name: 'Fruit', quantity: 4 },
{ name: 'N26 Metal Card', quantity: 1 },
{ name: 'Flour', quantity: 2 },
{ name: 'Chocolate', quantity: 2 },
{ name: 'Vegetables', quantity: 3 }
])
const removeItem = itemToBeRemoved => {
setGroceries(items => items.filter(item => item !== itemToBeRemoved))
}
return (
<ul>
{groceries.map(item => {
const persistentKey = objectToKey(item)
return (
<li key={objectToKey(item)}>
{item.quantity}x {item.name}
<button onClick={() => removeItem(item)}>Remove</button>
<small>(persistentKey: {objectToKey(item)})</small>
</li>
)
})}
</ul>
)
}
render(<GroceryList />, document.getElementById('root'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment