skip to Main Content

My React App pulls data from a Djano REST API through the api.js file below.

api.js

const URLS = {

  PRODUCTS: "http://127.0.0.1:8000/api/products/",
  PRODUCT: (id) => `http://127.0.0.1:8000/api/products/${id}`,

};

const wrappedFetch = (...args) => {
  return fetch(...args).then((res) => {
    return res.json();
  });
};

const get = (url) => wrappedFetch(url);


// PRODUCT API
const loadProducts = () => get(URLS.PRODUCTS);
const loadProduct = (id) => get(URLS.PRODUCT(id));

export {

  loadProducts,
  loadProduct,

};

The data does not successfully render at its first load and identifies an issue in my useAllProducts.js file below.

import { useQuery } from "react-query";
import { loadProducts } from "./api/api";

function useAllProducts() {
  const { data = [] } = useQuery("products", loadProducts);
  console.log(data)
 
  return data.products.map(({ id }) => id);
}

export default useAllProducts;

The error is undefined is not an object (evaluating 'data.products.map')

At useAllProduts.js
Once I change return data.products.map(({ id }) => id); to return data.map(({ id }) => id); and back again to return data.products.map(({ id }) => id);, the products render successfully.

Replacing the above with

return data.products && products.map(({ id }) => id);

does not solve the error.

Also when I refresh the page, the same error persists (undefined is not an object (evaluating 'data.products.map'). I think my App renders data before it’s populated and possibly needs to add a condition or async/await in my api.js.

How do I solve this: I have tried adding async/await, but I feel I blundered and therefore did not work.

I know there are similar questions, but my api.js file is quite different.

Please help me.

2

Answers


  1. return data.products && products.map(({ id }) => id); is incorrect because products is undefined in products.map. You’d want to do something more like return data.products && data.products.map(({ id }) => id);.

    On the initial render when data has yet to be fetched (and cached) data.products is undefined. When you change the code to data.map(({ id }) => id); and back and it works, it’s likely that the hook is able to read the cached response and data.products is defined.

    If you are expecting the fetched data to have a products property that is the array, then you can provide a better fallback value, and use a null-check on the potentially undefined property accesses.

    Examples:

    function useAllProducts() {
      const { data = { products: [] } } = useQuery("products", loadProducts);
     
      return (data.products ?? []).map(({ id }) => id);
    }
    
    function useAllProducts() {
      const { data } = useQuery("products", loadProducts);
     
      return (data?.products ?? []).map(({ id }) => id);
    }
    
    Login or Signup to reply.
  2. import { useQuery } from "react-query";
    import { loadProducts } from "./api/api";
    
    function useAllProducts() {
      const { data = [] } = useQuery("products", loadProducts);
      console.log(data)
     
      return data.products ? data.products.map(({ id }) => id) :[];
    }
    
    export default useAllProducts;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search