Задать вопрос
i229194964
@i229194964
Веб разработчик

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

Здравствуйте! Столкнулся с проблемой в React-приложении, получаю ошибку
TypeError: Cannot read properties of undefined (reading 'completedCourses')
at Stats (localhost:3001/static/js/bundle.js:5628:43)
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(() => {
    fetchStats();
  }, []);

  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),
              totalProgress: Math.min(100, Math.max(0, parseInt(stat?.totalProgress || 0)))
            }))
        : [];

      console.log('Processed Stats:', { courseStats, userStats });

      setStats({
        courseStats,
        userStats,
        loading: false,
        error: null
      });
    } catch (error) {
      console.error('Error fetching stats:', error);
      setStats({
        courseStats: [],
        userStats: [],
        loading: false,
        error: error.message || 'Ошибка при загрузке статистики'
      });
    }
  };

  if (stats.loading) {
    return (
      <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '200px' }}>
        <CircularProgress />
      </Box>
    );
  }

  if (stats.error) {
    return (
      <Box sx={{ p: 3 }}>
        <Typography color="error">{stats.error}</Typography>
      </Box>
    );
  }

  if (!stats.courseStats.length && !stats.userStats.length) {
    return (
      <Box sx={{ p: 3 }}>
        <Typography>Нет доступных данных для отображения</Typography>
      </Box>
    );
  }

  return (
    <Box sx={{ p: 3 }}>
      <Typography variant="h4" sx={{ mb: 4, color: '#5D4037' }}>
        Статистика
      </Typography>
      
      <Grid container spacing={3}>
        {stats.courseStats.length > 0 && (
          <Grid item xs={12} md={6}>
            <Paper sx={{ p: 3, bgcolor: '#f5e6d3' }}>
              <Typography variant="h6" sx={{ color: '#5D4037', mb: 2 }}>
                Статистика по курсам
              </Typography>
              {stats.courseStats.map((stat, index) => (
                <Box key={index} sx={{ mb: 2, p: 2, bgcolor: 'rgba(255, 255, 255, 0.5)', borderRadius: 1 }}>
                  <Typography variant="subtitle1" sx={{ color: '#5D4037', fontWeight: 'bold' }}>
                    {stat.title}
                  </Typography>
                  <Typography variant="body2" sx={{ color: '#2E7D32' }}>
                    Прошли курс: {stat.completed}
                  </Typography>
                  <Typography variant="body2" sx={{ color: '#1976D2' }}>
                    В процессе: {stat.inProgress}
                  </Typography>
                </Box>
              ))}
            </Paper>
          </Grid>
        )}

        {stats.userStats.length > 0 && (
          <Grid item xs={12} md={6}>
            <Paper sx={{ p: 3, bgcolor: '#f5e6d3' }}>
              <Typography variant="h6" sx={{ color: '#5D4037', mb: 2 }}>
                Статистика по пользователям
              </Typography>
              {stats.userStats.map((stat, index) => (
                <Box key={index} sx={{ mb: 2, p: 2, bgcolor: 'rgba(255, 255, 255, 0.5)', borderRadius: 1 }}>
                  <Typography variant="subtitle1" sx={{ color: '#5D4037', fontWeight: 'bold' }}>
                    {stat.username}
                  </Typography>
                  <Typography variant="body2" sx={{ color: '#2E7D32' }}>
                    Завершенные курсы: {stat.completedCourses}
                  </Typography>
                  <Typography variant="body2" sx={{ color: '#1976D2' }}>
                    Общий прогресс: {Math.round(stat.totalProgress)}%
                  </Typography>
                </Box>
              ))}
            </Paper>
          </Grid>
        )}
      </Grid>
    </Box>
  );
}

export default Stats;

Как лучше обработать случай, когда user или completedCourses не определены, чтобы компонент не выдавал ошибку, а возвращал, например, "Нет данных"? Буду благодарен за любые советы!
  • Вопрос задан
  • 58 просмотров
Подписаться 1 Простой 1 комментарий
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы