Handling lists and keys in React is essential for rendering multiple components dynamically and efficiently updating the DOM. This chapter will cover the fundamentals of rendering lists, the importance of keys, and advanced techniques for managing dynamic lists in React applications. By the end of this chapter, you will have a thorough understanding of how to work with lists and keys in React, enabling you to create complex and performant user interfaces.
Rendering lists in React is straightforward. You typically use the JavaScript map()
function to transform an array of data into an array of React elements.
import React from 'react';
function NumberList({ numbers }) {
const listItems = numbers.map((number) =>
{number}
);
return (
{listItems}
);
}
export default NumberList;
NumberList
component receives a prop numbers
(an array).map()
function to create a new array of <li>
elements, one for each number.<li>
element has a key
prop, which we’ll discuss in detail later.
- 1
- 2
- 3
Keys help React identify which items have changed, are added, or are removed. They should be given to the elements inside the array to give the elements a stable identity.
When updating a list, React needs to determine which items need to be re-rendered. By providing unique keys, React can keep track of each item between updates, optimizing rendering performance.
Keys should be unique among siblings but don’t need to be globally unique. Avoid using indexes as keys if the list can change because this can lead to inefficient updates and bugs.
import React from 'react';
function TodoList({ todos }) {
const listItems = todos.map((todo) =>
{todo.text}
);
return (
{listItems}
);
}
export default TodoList;
todos
array contains objects with id
and text
properties.<li>
element uses todo.id
as the key, ensuring a unique and stable identifier
- Learn React
- Build a Todo App
- Master JavaScript
You can embed the map()
function directly inside JSX for cleaner and more readable code.
import React from 'react';
function TodoList({ todos }) {
return (
{todos.map((todo) => (
-
{todo.text}
))}
);
}
export default TodoList;
map()
function is used directly within the JSX, making the code more concise.You can conditionally render lists based on certain criteria.
import React from 'react';
function TodoList({ todos, showCompleted }) {
return (
{todos.map((todo) => {
if (!showCompleted && todo.completed) {
return null;
}
return (
-
{todo.text}
);
})}
);
}
export default TodoList;
showCompleted
prop determines whether to render completed todos.map()
checks this prop and decides whether to render each item.
- Learn React
- Build a Todo App
For more complex data structures, you might need to render nested lists or use more sophisticated logic.
import React from 'react';
function CategoryList({ categories }) {
return (
{categories.map((category) => (
-
{category.name}
{category.items.map((item) => (
- {item.name}
))}
))}
);
}
export default CategoryList;
categories
array contains nested items
arrays.map()
calls render the main categories and their respective items.
-
Fruits
- Apple
- Banana
-
Vegetables
- Carrot
- Broccoli
Handling dynamic updates to lists involves adding, updating, and removing items.
import React, { useState } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Learn React' },
{ id: 2, text: 'Build a Todo App' },
]);
const [newTodo, setNewTodo] = useState('');
const addTodo = () => {
const newId = todos.length ? todos[todos.length - 1].id + 1 : 1;
const newTodoItem = { id: newId, text: newTodo };
setTodos([...todos, newTodoItem]);
setNewTodo('');
};
return (
setNewTodo(e.target.value)}
/>
{todos.map((todo) => (
- {todo.text}
))}
);
}
export default TodoApp;
todos
state holds the list of todo items.newTodo
state stores the value of the new todo item being added.addTodo
function creates a new todo item and updates the todos
state.
- Learn React
- Build a Todo App
import React, { useState } from 'react';
function TodoApp() {
const [todos, setTodos] = useState([
{ id: 1, text: 'Learn React' },
{ id: 2, text: 'Build a Todo App' },
]);
const removeTodo = (id) => {
const updatedTodos = todos.filter(todo => todo.id !== id);
setTodos(updatedTodos);
};
return (
{todos.map((todo) => (
-
{todo.text}
))}
);
}
export default TodoApp;
removeTodo
function filters out the todo item with the specified id and updates the todos
state.
-
Learn React
-
Build a Todo App
In this practical example, we will create a simple contact list application. The application will allow users to view a list of contacts, add new contacts, and remove existing contacts. This will demonstrate the concepts of rendering lists, using keys, and handling dynamic updates in React.
The App
component will manage the state of the contact list and handle adding and removing contacts.
import React, { useState } from 'react';
import ContactList from './ContactList';
import AddContactForm from './AddContactForm';
function App() {
const [contacts, setContacts] = useState([
{ id: 1, name: 'Alice', phone: '123-456-7890' },
{ id: 2, name: 'Bob', phone: '987-654-3210' },
]);
const addContact = (name, phone) => {
const newId = contacts.length ? contacts[contacts.length - 1].id + 1 : 1;
const newContact = { id: newId, name, phone };
setContacts([...contacts, newContact]);
};
const removeContact = (id) => {
const updatedContacts = contacts.filter(contact => contact.id !== id);
setContacts(updatedContacts);
};
return (
Contact List
);
}
export default App;
The ContactList
component will render the list of contacts and provide a button to remove each contact.
import React from 'react';
function ContactList({ contacts, removeContact }) {
return (
{contacts.map((contact) => (
-
{contact.name} - {contact.phone}
))}
);
}
export default ContactList;
The AddContactForm
component will provide a form to add new contacts.
import React, { useState } from 'react';
function AddContactForm({ addContact }) {
const [name, setName] = useState('');
const [phone, setPhone] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (name && phone) {
addContact(name, phone);
setName('');
setPhone('');
}
};
return (
);
}
export default AddContactForm;
The full application combines these components to provide a functional contact list where users can add and remove contacts dynamically.
App
component manages the state of the contact list (contacts
).addContact
function adds a new contact to the list.removeContact
function removes a contact from the list based on its id.ContactList
component renders each contact in a list with a remove button.AddContactForm
component handles the input for new contacts and calls addContact
on form submission.
Output:
Contact List
-
Alice - 123-456-7890
-
Bob - 987-654-3210
Working with lists and keys is a fundamental aspect of React development. By understanding how to render lists, use keys effectively, and handle dynamic updates, you can create efficient and interactive user interfaces. This chapter covered basic to advanced techniques, including rendering simple and complex lists, using keys for efficient updates, and managing dynamic list operations such as adding and removing items. Mastering these concepts will enable you to build robust and performant React applications. Happy coding !❤️