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.stack.imgur.com/MrYXk.png)

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Toto
  • 13
  • 3
  • The `fetchRecords` function as written will always return `undefined`. You need to `await` on `fetch` instead of using `.then`. – tromgy Jan 13 '23 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. – tromgy Jan 13 '23 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! – Toto Jan 13 '23 at 13:54
  • @tromgy Display() { const [records, setRecords] = useState(); const fetchRecords = () => { 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; setRecords(data); if (!response.ok) { ... }); } useEffect(() => { // let dataFetched = fetchRecords(); fetchRecords(); }, []); – Toto Jan 13 '23 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. – Emanuele Scarabattoli Jan 13 '23 at 14:45
  • Additionally, are you sure that the request is succeeding? Check the dev tools network tab, if you didn't checked already. – Emanuele Scarabattoli Jan 13 '23 at 14:50

0 Answers0