0

My super-simple application fails to fetch and display data. help me to solve the problem , please, I'm stuck.

my api seems to be basically working, but it fails somewhere on the way to client.

hope, the code snippets I attach will be enough.

thanx!

app.js (mongoDB connection string is hidden):

var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
const bodyParser = require('body-parser');
const cors = require("cors");

var app = express();  
app.set('veiw engine', 'ejs')
app.use(cors());
app.use(logger('dev'));
app.use(express.json());
app.use(bodyParser.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

const { MongoClient } = require("mongodb");
const uri = "...intentionally hidden...";
const client = new MongoClient(uri);
const database = client.db('holdocsDB');
const records = database.collection('records');

app.get('/users', async (req, res) => {
    // try {
        const cursor = await records.find();  
        const results = await cursor.toArray();
        const objectStringified = results.map(record => JSON.stringify(record));
        const recordsNoId = [];
        for ( recordString of objectStringified ) {
          record = JSON.parse(recordString);
          let recordValuesArr = Object.values(record);
          let recordNoId = recordValuesArr.slice(1);
          recordsNoId.push(recordNoId);}      
        } 
      )
    
// catch 404 and forward to error handler
app.use(function(req, res, next) {
    next(createError(404));
  });
  
  // error handler
  app.use(function(err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};
  
    // render the error page
    res.status(err.status || 500);
    res.json('error');
  });

module.exports = app;

SingleRecord.js

const SingleRecord = (firstName, age) => {
    return (
      <li className="singe-record">
        {firstName} is {age} years old.
      </li>
    );
  }
  
  export default SingleRecord;

Display.js:

import React from 'react';
import { useState, useEffect } from 'react';
import './display.css';
import SingleRecord from './SingleRecord';

function Display() {
  const [records, setRecords] = useState();
  const fetchRecords = () => {
    let data;
    fetch('http://localhost:3001/users')
        .then(async response => {
            const isJson = response.headers.get('content-type')?.includes('application/json');           
            const data = isJson ? await response.json() : null;

            // check for error response
            if (!response.ok) {
                // get error message from body or default to response status
                const error = (data && data.message) || response.status;
                return Promise.reject(error);
            }
        })
        .catch(error => {
            console.error('There was an error!', error);
        });
    return data;
  }

    useEffect(() => {  
        let dataFetched = fetchRecords();      
    // eslint-disable-next-line react-hooks/exhaustive-deps
        setRecords(dataFetched);
    }, []);

    console.log("records after fetching data:" + records);

    if (!records) {
        return null;
    }

    return (
        <div className="records-display">
          <h2>Records:</h2>
          <ul className ="records-list">
            {records && records.map(record => (
              <SingleRecord firstName={record.firstName} age={record.age} />
            ))}
          </ul>      
        </div>
    );
}

export default Display;


output in chrome console: (https://i.sstatic.net/MrYXk.png)

6
  • The fetchRecords function as written will always return undefined. You need to await on fetch instead of using .then. Commented Jan 13, 2023 at 13:04
  • 1
    Or you could set your state (setRecords) inside .then once you get the JSON data, and the fetchRecords function in this case doesn't need to return anything. Commented Jan 13, 2023 at 13:07
  • Thanx @tromgy! I moved the (setRecords) inside .then (as you proposed), but it still doesn't work. There is a good chance, I didn't understand your answer and the actual reason behind the bug. Could you expand on this? I am attaching the edited code, Thanks a lot! Commented Jan 13, 2023 at 13:54
  • @tromgy Display() { const [records, setRecords] = useState(); const fetchRecords = () => { fetch('localhost:3001/users') .then(async response => { const isJson = response.headers.get('content-type')?.includes('application/json'); const data = isJson ? await response.json() : null; setRecords(data); if (!response.ok) { ... }); } useEffect(() => { // let dataFetched = fetchRecords(); fetchRecords(); }, []); Commented Jan 13, 2023 at 13:58
  • 1
    @Toto, please, update the question instead of adding the question updates here. If you want to keep both original and updated question, please, add a section like "Edit", then add the edits under that section. Commented Jan 13, 2023 at 14:45

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.