1

For some reason, the loading state doesn't change when I'm using this method to fetch from the API.

How to display "Loading..." while the call is running.

  • async-await doesn't work either, that's why I'm using this method to fetch.
const [product, setProduct] = useState({});
const [loading, setLoading] = useState(false);
const productId = 1;

const fetchProduct = () => {
  setLoading(true);
  //here commerce is my api, so i fetched the product details and set it to the product state
  commerce.products.retrieve(productId).then(data => setProduct(data));
  setLoading(false);
}

useEffect(() => {
  fetchProduct();
})

if (loading) {
  return (
    <span>Loading...</span>
  )
}

return (
  <h1>{product.name}</h1>
)
1
  • Note that useEffect() without second argument (dependencies) will trigger after each render. Make sure to pass an empty array if you only want to fire a request on component mount without making requests thereafter. eg. useEffect(() => { code... }, []) Commented Jun 22, 2021 at 15:34

4 Answers 4

1

You have to set the complete state inside the promise result just after retrive the products

const fetchProduct = () => {
    setLoading(true);
    commerce.products.retrieve(productId)
        .then(data => {
                       setProduct(data)
                       //HERE
                       setLoading(false);
                       });
}
Sign up to request clarification or add additional context in comments.

Comments

1

I think there's two way for doing it corresponding of your code.

First, this one:

const [isLoading, setIsLoading] = useState(false);

const handleFetch = () => {
  setIsLoading(true);
  someApiCall().then((r) => {
    setIsLoading(false);
  });
};

Or

const [isLoading, setIsLoading] = useState(false);

const handleFetch = async () => {
  setIsLoading(true);
  await someApiCall();
  setIsLoading(false);
};

Comments

0

you didn't use async await at all but if you donn't wana use async await then u should use following

 const fetchProduct = () => {
    setLoading(true);
    //here commerce is my api, so i fetched the product details and set it to the product state
    commerce.products.retrieve(productId).then(data => {
      setProduct(data);
      setLoading(false);
      }).catch(() => {
        setLoading(false);
     })
    

    }

1 Comment

I suggest removing setLoading(false) from the then() and catch() callbacks, and instead use a finally() callback which is triggered on both success and failure.
0

Forget about loading.

You can infer if the data is loading or not from the value of product.

const Component = () => {
    const [product, setProduct] = useState(null);

    useEffect(() => {
        const getProducts = async () => {
            const data = await commerce.products.retrieve(productId)
            setProduct(data);
        };
        getProducts();
    }, []);

    if (product === null) {
        return <span>Loading...</span>;
    }

    return <h1>{product.name}</h1>;
}

If you really wanted to use a separate loading variable then you would have it default to true and set it to false at the same time you give a value to product.

Comments

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.