Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React.js: how to generate a key when doing optimistic create?

Working with React.js is really enjoyable.

I built a simple comment app based on the official tutorial.

You can add, edit, and delete comments. They are pulled via GET every 10 seconds.

At one point, the tutorial mentions optimistic updates: updating the UI before the server has responded in the case of a create, update or delete operation.

Since comments are part of a list, React suggests to assign a unique key to each comment.

I therefore use the database id of each comment as a key. That works fine for update and delete operations.

However, in the case of a create operation, I do not know the database id of a comment until it has been actually created server-side, and therefore I don't know what value to assign to the key.

At that point in time, the comment is added to the comment list but has no key/ID and therefore cannot be edited or deleted, until the list gets updated during the next API poll.

Can I work around that?

like image 348
Jérémy F. Avatar asked Jul 20 '15 00:07

Jérémy F.


1 Answers

If you need the key to remain the same across updates, one option is to assign a temporary id to to an unused property. Then, use a function to retrieve the correct key for your list item models. As long as you account for the tempId property when updating the item, you can keep the key the same as long as the list remains in memory.

While you may not always care if the optimistic item gets removed and re-added, it can simplify your CSS when using on-enter or on-leave animations in your list. This also helps when you have stateful list item components.

Example:

let tempIds = 1; // 1 and up are truthy

// where ever you add the new item to your list
const newList = [...list, {...newItem, tempId: tempIds++}];

// get the right id
function getKey(instance) {
  if (instance.tempId) {
    return instance.tempId;
  } else {
    return instance.id;
  }
}

// in your list render function
<List>
  {list.map(model => (
    <Item
      key={getKey(model)}
      //other props go here
    />
  ))}
</List
like image 94
meticoeus Avatar answered Nov 08 '22 22:11

meticoeus