DEV Community

Ramesh Vishnoi
Ramesh Vishnoi

Posted on • Updated on

Right Usage of Keys in React

Usage

Keys are used by React internal algorithm (Reconciliation or React’s “diffing” algorithm) to determine what changes it needs to apply to UI in while updating UI.

Before React, Browsers were repainting the entire UI for every change, even if it's small subset of the screen which needs a repaint.

React have very efficient algorithm where it creates a virtual dom tree of a complete app containing components and its dom element. When there is a change required in UI as an effect of user interaction (for eg - toggle between dark and light theme) or some change triggered by backend (notification received) You can read more about it here

Coming back to the importance/usage of keys, React depend on you (as a developer) to use permanent and unique property as Keys so that it can optimize performace or repaint screen in most efficent manner.

Side Effect of incorrent key usage

When a key of a component is updated (changed from a to b), React discards/flushes the current component and creates a new instance of the component.

Here, component lifecycle methods are invoked such as componentDidMount, ComponentWillMount (for newly mounted instance) and componentUnMount (for old instance)

For eg - Network call in componentDidMount will be invoked again which may or maynot be desired.

Do's

  • Use unique and permanent properties as keys.
  • Keys should be unique within its siblings. No need to make it unique across the complete app. for eg -
const Item = (item) => {
    return (
        <li>{item.value}</li>
    )
}

const Home = () => {
    const itemList = [{id: '#1',value: 'hello world'}, {id: '#2',value: 'second line'}, {id: '#3',value: 'third line'}]
    return (
        <div>
        <ul>
            {itemList.map((item) => {
                return <Item key={item.id} item={item}/>
            })}
        </ul>
        // incorrect or no need for prefixing random text
        <ul>
            {itemList.map((item) => {
                return <Item key={'secondarray'-${item.id}} item={item}/>
            })}
        </ul>
        </div>
    )
}
Enter fullscreen mode Exit fullscreen mode

Don'ts

  • Do not generate ids in runtime as keys. On every render cycle(runtime) new ids will be generate. Which means, unnecessary component mount and unmounting. for eg -
import { nanoid } from 'nanoid'

const Home = () => {
    const itemList = ['hello world', 'second line', 'third line']
    return (
        <ul>
            {itemList.map((item) => {
                return <li key={nanoid()}>{item}</li>
            })}
        </ul>
    )
}
Enter fullscreen mode Exit fullscreen mode
  • No need to pass keys down the component tree
// incorrect usage
const Item = (item) => {
    return (
        <li key={item.id}>{item.value}</li>
    )
}

// correct usage
const Item = (item) => {
    return (
        <li>{item.value}</li>
    )
}

const Home = () => {
    const itemList = [{id: '#1',value: 'hello world'}, {id: '#2',value: 'second line'}, {id: '#3',value: 'third line'}]
    return (
        <ul>
            {itemList.map((item) => {
                return <Item key={item.id} item={item}/>
            })}
        </ul>
    )
}
Enter fullscreen mode Exit fullscreen mode
  • Using Index from Array should be last resort and internally React uses indes as keys if not provided.

Top comments (0)