Как исправить ошибку TypeError: Cannot read properties of undefined (reading 'completedCourses') в React-компоненте?

Здравствуйте! Я столкнулся с проблемой в своем React-приложении. Получаю следующую ошибку: <br/> TypeError: Cannot read properties of undefined (reading 'completedCourses') <br/> в компоненте Stats ( <a href="http://localhost:3001/static/js/bundle.js:5628:43" rel="nofollow">localhost:3001/static/js/bundle.js:5628:43</a> ) <br/> <pre><code class="javascript">import React, { useState, useEffect } from 'react';
import {
  Box,
  Paper,
  Typography,
  Grid,
  CircularProgress
} from '@mui/material';
import api from '../services/api';

function Stats() {
  const [stats, setStats] = useState({
    courseStats: [],
    userStats: [],
    loading: true,
    error: null
  });

  useEffect(() =&gt; {
    fetchStats();
  }, []);

  const fetchStats = async () =&gt; {
    try {
      const response = await api.get('/admin/statistics');
      console.log('Raw API Response:', response);

      if (!response?.data) {
        throw new Error('No data received from API');
      }

      const courseStats = Array.isArray(response.data?.courseStats) 
        ? response.data.courseStats
            .filter(Boolean)
            .map(stat =&gt; ({
              title: String(stat?.title || 'Без названия'),
              completed: parseInt(stat?.completed || 0),
              inProgress: parseInt(stat?.inProgress || 0)
            }))
        : [];

      const userStats = Array.isArray(response.data?.userStats) 
        ? response.data.userStats
            .filter(Boolean)
            .map(stat =&gt; ({
              username: String(stat?.username || 'Неизвестный пользователь'),
              completedCourses: parseInt(stat?.completedCourses || 0),
              totalProgress: Math.min(100, Math.max(0, parseInt(stat?
  • 13 ноября 2024 г. 8:03
Ответы на вопрос 1
Ошибка `TypeError: Cannot read properties of undefined (reading 'completedCourses')` возникает, когда вы пытаетесь получить доступ к свойству `completedCourses` объекта, который равен `undefined`. Эта ситуация может произойти, если данные, полученные от API, не содержат ожидаемой структуры.

Вот несколько шагов, которые помогут вам исправить эту ошибку:

1. **Проверка наличия данных в ответе API**: Убедитесь, что вы проверяете и обрабатываете данные, полученные от API, прежде чем пытаться получить доступ к их свойствам. Вы уже частично это делаете с помощью `Array.isArray(response.data?.userStats)`, но можете улучшить проверки.

2. **Совершенствование обработки данных**: Если объект `stat` может быть `undefined`, вы должны добавить дополнительные проверки. Вместо непосредственного обращения к его свойствам, используйте оператор опциональной цепочки (`?.`) для безопасного доступа.

3. **Улучшение обработки ошибок**: В результате обработки ошибок добавьте подходящий вывод сообщений в консоль, чтобы вы могли лучше понять, когда ваши данные не соответствуют ожиданиям.

Вот как можно изменить ваш код, чтобы добавить дополнительные проверки:

```javascript
const fetchStats = async () => {
  try {
    const response = await api.get('/admin/statistics');
    console.log('Raw API Response:', response);

    if (!response?.data) {
      throw new Error('No data received from API');
    }

    const courseStats = Array.isArray(response.data?.courseStats) 
      ? response.data.courseStats
          .filter(Boolean)
          .map(stat => ({
            title: String(stat?.title || 'Без названия'),
            completed: parseInt(stat?.completed || 0),
            inProgress: parseInt(stat?.inProgress || 0)
          }))
      : [];

    const userStats = Array.isArray(response.data?.userStats) 
      ? response.data.userStats
          .filter(Boolean)
          .map(stat => ({
            username: String(stat?.username || 'Неизвестный пользователь'),
            completedCourses: parseInt(stat?.completedCourses || 0), // safe access
            totalProgress: Math.min(100, Math.max(0, parseInt(stat?.totalProgress || 0))) // safe access
          }))
      : [];

    // Обновление состояния
    setStats({
      courseStats,
      userStats,
      loading: false,
      error: null
    });
  } catch (error) {
    console.error('Error fetching stats:', error);
    setStats({
      courseStats: [],
      userStats: [],
      loading: false,
      error: error.message || 'Произошла ошибка при получении данных'
    });
  }
};
```

### Дополнительные рекомендации
- Убедитесь, что API действительно возвращает ожидаемую структуру данных. Можно временно вывести в консоль весь ответ, чтобы видеть, каковы данные.
- Проверьте, вызывается ли метод `fetchStats` и имеет ли он доступ к API.
- Если данные могут меняться, рассмотреть вариант добавления значений по умолчанию для свойств, которые часто могут отсутствовать.

Такой подход поможет избежать ошибки и сделать ваш код более устойчивым к проблемам с данными.
Похожие вопросы