Skip to content

Instantly share code, notes, and snippets.

@sambostock
Last active September 26, 2019 00:19
Show Gist options
  • Save sambostock/099df9eac4502490a5b9d4e6744960b4 to your computer and use it in GitHub Desktop.
Save sambostock/099df9eac4502490a5b9d4e6744960b4 to your computer and use it in GitHub Desktop.
Keys in React and Vue

React Keys

Consider the difference between these:

function NameList({names}) {
  return (<ul>{names.map((name, index) =>
    <li key={index}>{name}</li>
  )}</ul>);
}

Given these names

<NameList names={['Bob', 'Charles']} />

It would render

<ul>
  <li key="0"><Bob/li>
  <li key="1"><Charles/li>
</ul>

If it re-renders with the names

<NameList names={['Alfred', 'Bob', 'Charles']} />

It would cause the following changes:

 <ul>
-  <li key="0"><Bob/li>
-  <li key="1"><Charles/li>
+  <li key="0">Alfred</li>
+  <li key="1">Bob</li>
+  <li key="2"><Charles/li>
 </ul>

Since the index key wasn't stable, as far as React is concerned, the two first <li> have changed, and a third one was added.

However, if you use name as the key

 function NameList({names}) {
   return (<ul>{names.map((name, index) =>
-    <li key={index}>{name}</li>
+    <li key={name}>{name}</li>
   )}</ul>);
 }

The same scenario would result in a much smaller change:

 <ul>
+  <li key="Alfred">Alfred</li>
   <li key="Bob"><Bob/li>
   <li key="Charles"><Charles/li>
 </ul>

Here, React can figure out that the two original <li> haven't changed, but a third one was prepended, so it just adds that.

Vue Keys

Consider the difference between these:

<template>
  <ul>
    <li v-for="(name, index) in names" :key="index">{{name}}</li>
  </ul>
</template>

Given these names

<NameList names={['Bob', 'Charles']} />

It would render

<ul>
  <li key="0"><Bob/li>
  <li key="1"><Charles/li>
</ul>

If it re-renders with the names

<NameList names={['Alfred', 'Bob', 'Charles']} />

It would cause the following changes:

 <ul>
-  <li key="0"><Bob/li>
-  <li key="1"><Charles/li>
+  <li key="0">Alfred</li>
+  <li key="1">Bob</li>
+  <li key="2"><Charles/li>
 </ul>

Since the index key wasn't stable, as far as Vue is concerned, the two first <li> have changed, and a third one was added.

However, if you use name as the key

 <template>
   <ul>
-    <li v-for="(name, index) in names" :key="index">{{name}}</li>
+    <li v-for="(name, index) in names" :key="name">{{name}}</li>
   </ul>
 </template>

The same scenario would result in a much smaller change:

 <ul>
+  <li key="Alfred">Alfred</li>
   <li key="Bob"><Bob/li>
   <li key="Charles"><Charles/li>
 </ul>

Here, Vue can figure out that the two original <li> haven't changed, but a third one was prepended, so it just adds that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment