← Назад к вопросам

Как отобразить список в компоненте?

2.3 Middle🔥 161 комментариев
#React

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Отображение списков в React компоненте

Отображение списков - одна из самых частых задач в фронтенде. В React для этого используется функция map(). Существует несколько подходов в зависимости от сложности данных и требований.

1. Базовый пример с map()

import React from 'react';

const UserList = () => {
  const users = [
    { id: 1, name: 'Алексей' },
    { id: 2, name: 'Виктория' },
    { id: 3, name: 'Дмитрий' }
  ];
  
  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

2. Отдельный компонент для элемента списка

// Компонент для одного элемента
const UserItem = ({ user }) => (
  <li className="user-item">
    <span className="user-name">{user.name}</span>
    <span className="user-email">{user.email}</span>
  </li>
);

// Компонент списка
const UserList = ({ users }) => (
  <ul className="user-list">
    {users.map((user) => (
      <UserItem key={user.id} user={user} />
    ))}
  </ul>
);

// Использование
const App = () => {
  const users = [
    { id: 1, name: 'Алексей', email: 'alex@example.com' },
    { id: 2, name: 'Виктория', email: 'vic@example.com' }
  ];
  
  return <UserList users={users} />;
};

3. Список с фильтрацией

const FilteredUserList = ({ users, filter }) => {
  const filteredUsers = users.filter((user) =>
    user.name.toLowerCase().includes(filter.toLowerCase())
  );
  
  return (
    <div>
      <input
        type="text"
        placeholder="Поиск..."
        value={filter}
        onChange={(e) => setFilter(e.target.value)}
      />
      
      <ul>
        {filteredUsers.length > 0 ? (
          filteredUsers.map((user) => (
            <li key={user.id}>{user.name}</li>
          ))
        ) : (
          <li>Пользователи не найдены</li>
        )}
      </ul>
    </div>
  );
};

4. Список с состоянием и обработчиками

import { useState } from 'react';

const InteractiveUserList = () => {
  const [users, setUsers] = useState([
    { id: 1, name: 'Алексей' },
    { id: 2, name: 'Виктория' }
  ]);
  const [selectedId, setSelectedId] = useState(null);
  
  const handleSelectUser = (id) => {
    setSelectedId(id);
  };
  
  const handleRemoveUser = (id) => {
    setUsers(users.filter((user) => user.id !== id));
  };
  
  return (
    <div>
      <ul className="user-list">
        {users.map((user) => (
          <li
            key={user.id}
            className={selectedId === user.id ? 'selected' : ''}
            onClick={() => handleSelectUser(user.id)}
          >
            <span>{user.name}</span>
            <button onClick={() => handleRemoveUser(user.id)}>Удалить</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

5. Виртуальный список для больших данных

// Для списков из тысяч элементов используй виртуализацию
import { FixedSizeList as List } from 'react-window';

const VirtualUserList = ({ users }) => (
  <List
    height={600}
    itemCount={users.length}
    itemSize={35}
    width="100%"
  >
    {({ index, style }) => (
      <div style={style} className="user-item">
        {users[index].name}
      </div>
    )}
  </List>
);

6. Список с загрузкой из API

import { useState, useEffect } from 'react';

const ApiUserList = () => {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    const fetchUsers = async () => {
      try {
        const response = await fetch('/api/users');
        if (!response.ok) throw new Error('Ошибка загрузки');
        const data = await response.json();
        setUsers(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    fetchUsers();
  }, []);
  
  if (loading) return <div>Загрузка...</div>;
  if (error) return <div>Ошибка: {error}</div>;
  
  return (
    <ul>
      {users.map((user) => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};

7. Правильное использование key

// ✅ Правильно - используй стабильный id
const users = [
  { id: 1, name: 'Алексей' },
  { id: 2, name: 'Виктория' }
];

users.map((user) => <li key={user.id}>{user.name}</li>);

// ❌ Неправильно - не используй index как key
users.map((user, index) => <li key={index}>{user.name}</li>);

// ❌ Неправильно - не используй случайные значения
users.map((user) => <li key={Math.random()}>{user.name}</li>);

8. Сортировка списка

const SortedList = ({ users }) => {
  const [sortBy, setSortBy] = useState('name');
  
  const sortedUsers = [...users].sort((a, b) => {
    if (sortBy === 'name') {
      return a.name.localeCompare(b.name);
    }
    if (sortBy === 'id') {
      return a.id - b.id;
    }
    return 0;
  });
  
  return (
    <div>
      <select value={sortBy} onChange={(e) => setSortBy(e.target.value)}>
        <option value="name">По имени</option>
        <option value="id">По ID</option>
      </select>
      
      <ul>
        {sortedUsers.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
};

9. Типизация с TypeScript

interface User {
  id: number;
  name: string;
  email: string;
}

interface UserListProps {
  users: User[];
  onSelect?: (user: User) => void;
}

const UserList: React.FC<UserListProps> = ({ users, onSelect }) => (
  <ul>
    {users.map((user) => (
      <li key={user.id} onClick={() => onSelect?.(user)}>
        {user.name}
      </li>
    ))}
  </ul>
);

Рекомендации

  1. Используй key - обязательно и правильно (id, не index)
  2. Разделяй компоненты - отдельный компонент для элемента
  3. Фильтрование перед map() - сначала filter, потом map
  4. Виртуализация для больших списков - react-window
  5. Типизируй данные - используй TypeScript
  6. Обработка пустого списка - показывай сообщение если список пуст
Как отобразить список в компоненте? | PrepBro