1

I have a backend connected to mongoDB through mongoose. I have a controller that send user data like this

const db = require("../../auth/models");
const User = db.user


const addProduct = (req, res) => {

User.findOne({
    username: req.body.username
}, function(err, user) {
    if (err) {
        res.status(500).send({ message: err })
    }else{
      
        user.store.push({
  
            id: req.body.id, 
            barcode: req.body.barcode,
            productName : req.body.productName,
            price : req.body.price,
            quantity: req.body.quantity
        
        })
        user.save(function(err, newUser) {
            if (err) {
                res.status(500).send({ message: err });
            } else {
                console.log(newUser);
                res.status(200).send({ message: "Product updated successfully!!"})
            }
        })
    }
})



res.status(200).send({ message: "Product updated successfully!!"})
};

function currentUserStoreData  (req, res)  {
    User.findOne({
        username: req.body.username
        }, function(err, user) {
        if (err) {
            res.status(500).send({ message: err })
        }else{
          return( user.store )
        }
      
    });
  
};



const sendProducts = (req, res) => {
console.log(currentUserStoreData );
  res.status(200).send(currentUserStoreData )
}

const  inventory = {
    addProduct,
    currentUserStoreData ,
    sendProducts,



};

module.exports = inventory

The user.store is in the form of an array but the console log is shown as undefined

then a routes file that has a POST request that is used to send the username to currentUserStoreData , And a GET request that gets the data returned by the currentUserStoreData which is caught by sendProductsData and the routes look like this

    const controller = require("../controller/inventory.controller")

module.exports = function(app) {
    app.use(function(req, res, next) {
      res.header(
        "Access-Control-Allow-Headers",
        "x-access-token, Origin, Content-Type, Accept"
      );
      next();
    });

    app.post('/api/inventory/currentUser', controller.currentUserStoreData );
     
    app.get('/api/inventory/getProductData', controller.sendProducts)
};

And

there is a service file that handles the routes through axios like this import axios from "axios";

const user = JSON.parse(localStorage.getItem("user"));
const username = user.username

const API_URL = "http://localhost:8080/api/inventory/";

const addProduct = (id, barcode, productName, price, quantity) => {
    return axios.post(API_URL + "additem" , {
        username,
        id,
        barcode,
        productName,
        price,
        quantity,
    });
};

const currentUsername = () => {
 return axios.post(API_URL + "currentUser" , {
     username,
 })
}

const fetchProduct = () => {
    return axios.get(API_URL + "getProductData")
}

export default {
    addProduct,
    fetchProduct,
    currentUsername
};

when I import it from another file to map through the array I have imported the service file and used it like this

  import React from 'react'
import ProductService from "../services/product-service.js"
import Table from 'react-bootstrap/Table'
import {useState, useEffect} from "react";

 ProductService.currentUsername();

const createRow = (product) => {
  console.log(product);

    return (
      
    <tr>
        <td>{product.id}</td>
        <td>{product.barcode}</td>
        <td>{product.productName}</td>
        <td>{product.price}</td>
        <td>{product.quantity}</td>
    </tr>
    )
}
const InventoryTable = () => {
  const [data, setData] = useState([]);

  useEffect(() => {
    ProductService
      .fetchProduct()
      .then(data => setData(data));
  }, []);
    console.log(data);
    return (
      <div>
        <Table striped bordered hover variant="dark">
          <thead>
            <tr>
              <th>Id</th>
              <th>barcode</th>
              <th>Product Name</th>
              <th>Price</th>
              <th>Quantity</th>
            </tr>
          </thead>
          <tbody>
          {data.map(createRow)}
          </tbody>
        </Table>
      </div>
    );
    }
  

export default InventoryTable

now I'm stuck plss help if wanted anything ask in comment section

Thanks for the help in advance.

1 Answers1

0

You can't access asynchronous code in the render of a React component as rendering is a completely synchronous process.

You can access the returned Promise and save the result locally to the component. Use a mounting useEffect hook to access the fetch service and save the resolved data into local state. Map the state to the rows.

import ProductService from "../services/product-service.js"

const InventoryTable = () => {
  const [data, setData] = React.useState([]);

  React.useEffect(() => {
    ProductService
      .fetchProduct()
      .then(data => setData(data));
  }, []);
  
  return (
    <div>
      <Table striped bordered hover variant="dark">
        <thead>
          <tr>
            <th>Id</th>
            <th>barcode</th>
            <th>Product Name</th>
            <th>Price</th>
            <th>Quantity</th>
          </tr>
        </thead>
        <tbody>
          {data.map(createRow())}
        </tbody>
      </Table>
    </div>
  );
};
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • 1
    I guess the complete api calling code block should be inside `useEffect` rather than just promise resolve function. Because that will prevent unnecessary api calling on component re-render. – Vivek Bani Jun 19 '21 at 06:22
  • @RajdeepDebnath Code is only called once per mounting, but yes, it is not intuitive as written. – Drew Reese Jun 19 '21 at 06:25
  • I understand that but my array of data is inside the Promise. I need access the information in that data inside the Promise so I could map through – K.V.Praneeth Reddy Jun 21 '21 at 05:12
  • @K.V.PraneethReddy I don't understand your comment. Can you clarify what you need to access in `data` and what you are trying to do then? – Drew Reese Jun 21 '21 at 15:51
  • OK. my issue is that whatever data sent by the API to frontend with the help of axios is coming as a promise, where it contains my data . All i need to know is how to access that data from promise. The Promise status is shown as pending I know that the promise has to be fulfilled but unable to do it – K.V.Praneeth Reddy Jun 22 '21 at 04:31
  • @K.V.PraneethReddy Have you tried my suggested solution for accessing the resolved value of the returned Promise? If you don't like Promise chains I can also share a solution using `async/await`. – Drew Reese Jun 22 '21 at 08:08
  • @DrewReese I have tried everything I have been googling for a couple of days now but cant get it. I have updated it now but still not working but I feel I Am closer to the solution please check the question I have edited it now with some solutions I got on internet but still not able to get it – K.V.Praneeth Reddy Jun 24 '21 at 05:24
  • @DrewReese check it now. Sorry, I thought you would take time to respond, so I commented first and then updated. pls check it – K.V.Praneeth Reddy Jun 24 '21 at 05:51
  • @K.V.PraneethReddy Are you having issue with the `ProductService.fetchProduct().then(data => setData(data));` part of the last snippet? – Drew Reese Jun 24 '21 at 06:02
  • @DrewReese I am unable to find where the problem is. It looks correct and there are no noticeable errors. The page that has this component renders too. but the data is what that I am unable to access to map through. I have checked mapping with raw data it worked. But there something wrong in the code that handles the data – K.V.Praneeth Reddy Jun 24 '21 at 06:09
  • @K.V.PraneethReddy It's at this point that a *running* codesandbox that reproduces the issue that we can inspect and live debug in would provide the most benefit. Is this something you can do? – Drew Reese Jun 24 '21 at 06:22
  • 1
    @DrewReese Thank You! for all the help. I started out with what you have said and finally solved my issue. I used the fetch() function and finally it worked – K.V.Praneeth Reddy Jun 27 '21 at 05:01