Ошибка ввода, но не тогда, когда внутри функции возврата React

#javascript #node.js #reactjs #mongodb #mongoose

Вопрос:

Я сталкиваюсь с проблемой, когда я получаю (ошибка типа: неопределенный не является объектом) при попытке вызвать атрибут объекта; однако эта ошибка возникает, когда она вызывается в функции возврата. Кроме того, ошибка возникает только при вызове атрибута объекта, а не самого объекта.

Я старался, чтобы включенный код был кратким; хотя я не совсем уверен, где возникает ошибка, поэтому может быть немного ненужной информации. Кроме того, в коде есть комментарии, в которых указано, где возникают и не возникают ошибки.

backend/models/course.js

 import mongoose from 'mongoose';

const courseSchema = mongoose.Schema({
    _id: Number,
    fields: Array,
    number: Number,
    name: String,
    minCredits: Number,
    maxCredits: Number,
    description: String,
    isSaved: { type: Boolean, default: false },
});

const course = mongoose.model('courses', courseSchema);

export default course;
 

backend/controllers/course.js

 import CourseData from '../models/course.js';

export const getSpecificCourse = async(req, res)=> {
    try {
        const selectedCourse = await CourseData.findOne({ _id: req.query.courseId });
        
        res.status(200).json(selectedCourse);
    } catch (error) {
        res.status(404).json({ message: error.message});
    }
}
 

backend/routes/course.js

 import express from 'express';
import { getSpecificCourse } from '../controllers/courses.js';

const router = express.Router();

router.get('/courseId', getSpecificCourse);

export default router;
 

backend/server.js

 import express from 'express';
import mongoose from 'mongoose';
import cors from 'cors';
import courseRoutes from './routes/courses.js';

const app = express();

app.use(express.json());
app.use(cors());
app.use('/courses', courseRoutes);

const PORT = process.env.PORT || 5000;

mongoose.connect(mongoUrl, {dbName: "dbName"}) // Hidden for privacy
    .then(() => app.listen(PORT, () =>
        console.log(`Connection is established and running on port: ${PORT}`)
        )).catch((err) => console.log(err.message));
 

frontend/src/components/CoursePage.js

 import React, { useEffect, useState } from 'react';
import { useParams } from "react-router-dom";
import axios from 'axios';
import './styles.css';

export function CoursePage() {
  const [isLoading, setLoading] = useState(true);
  const [course, setCourse] = useState()
  const { courseId } = useParams()

  const url = 'http://localhost:5000/courses/courseId/?courseId='   courseId;

  useEffect(() => {
    axios.get(url).then( (selectedCourse) => {
        setCourse(selectedCourse.data);
        setLoading(false);
    } )
  }, [])

  console.log(course); // results in no error
  console.log(course.number); // results in an error (occurs when calling any attribute)

  if (isLoading) {
    return <div>Loading...</div>
  }
    
  return (
    <div>
      {console.log(course)} // results in no error
      {console.log(course.number)} // results in no error (consistent with each attribute)
    </div>
  );
}
 

Ответ №1:

Во-первых, загрузка состояний начинается как true, а курс начинается как неопределенный:

 const [isLoading, setLoading] = useState(true);
const [course, setCourse] = useState()
 

А затем вы попытаетесь получить доступ к курсу до того, как он будет определен:

 // now the course is not defined yet.
console.log(course); // results in no error
console.log(course.number); // results in an error (occurs when calling any attribute)

if (isLoading) {
  return <div>Loading...</div>
}
 

Если вы измените код на:

 if (isLoading) {
  return <div>Loading...</div>
}

console.log(course); // results in no error
console.log(course.number); // results in an error (occurs when calling any attribute)
 

Ваш код go работает без каких-либо ошибок, потому что загрузка устанавливается в значение false только в том случае, если состояние курса установлено для полученного объекта.