5

If I want to call API after the first rendering of component, I know we have useEffect hook to call the API method. (I am talking about functional components only. No class component).

Is there any way, I can call the API before my component renders the first time.

The reason for this question is, If some UI part is dependent on API, I do not want to show any incomplete information to the user on the first render also, which will be changed once I get the data from API. This seems to be a bad experience with UI.

Edit: I got a couple of advice to use useLayoutEffect or any consumable flag to check if it is rendered or not. I have checked useLayoutEffect does not work, and by using the consumable flag, we are increasing the complexity only.

Do we have any better way for this?

Nimish goel
  • 2,561
  • 6
  • 27
  • 42
  • Since before and after render are milliseconds apart then how do you think before render will make a difference to after render? In both cases you have to render something (like loading). – HMR Apr 20 '20 at 12:56

5 Answers5

2

I think useLayoutEffect can be used for something like this, by passing in an empty array as second argument. useLayoutEffect(() => {...}, []);

Updates scheduled inside useLayoutEffect will be flushed synchronously, before the browser has a chance to paint.

Although you can always fetch the data in the parent component and pass it as props. Or - if you don't mind it being an experimental feature for now - React Suspense is trying to solve this exact problem.

maten
  • 566
  • 6
  • 17
  • 2
    " before the browser has a chance to paint.", but not before component rendered – Kyr Apr 20 '20 at 12:33
  • @Kyr that's true, I edited my answer to provide alternative methods – maten Apr 20 '20 at 12:37
  • 1
    @Nimishgoel You are correct. However, there is no built-in hook for this. Even ```componentWillMount``` is deprecated. You can write a custom hook like this one: https://stackoverflow.com/a/57073500/12402992, or use one of the 2 alternate options – maten Apr 20 '20 at 12:40
  • @Kyr what does it mean for a component to render? I thought it was rendered when it was rasterized by the GPU and painted on the screen – duhaime Feb 25 '21 at 01:30
  • @duhaime, I think that the "render" in the context of the react can be considered a returning from the component (render function) updated part of the virtual DOM, goes right? – Kyr Feb 25 '21 at 17:20
  • @Kyr yes I think you're right! I was underthinking the situation :/ – duhaime Feb 26 '21 at 12:38
1

You can have a spinner or loading component be rendered first conditionally (isLoading for example):

if(isLoading) return <Spinner />

and have the api call set (isLoading) to false on status 200 for example.

John Dough
  • 35
  • 7
0

There are no correct ways to make API call before component rendered from the same component.

You may preferred make API call in parent component and render presentation component when and only when have consumable data.

Another workaround for such case is keep consumable flag inside component, make request inside useEffect, render nothing or some kind loader and render something only when request completed with success.

Kyr
  • 887
  • 7
  • 11
0

on calling api it is not responding exact on its first render but giving exact response when it's being hit second time

Azaz Ahmed
  • 91
  • 1
  • 5
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 25 '22 at 08:14
0

Just came across something, which may help someone in future. So we can use some library but the specific one I would mention here is React Query

React query does exactly what we are trying to achieve, the hooks like useQuery fetch data as soon as rendering starts so you don’t have to wait until react loads the entire component as follows

// with react query
const { status, data, error, isFetching } = useQuery(
  ['data'],
  async () => {
    const data = await (
      await fetch(`${API_BASE_URL}/data`)
    ).json()
    return data
  }
)


// without react query
useEffect(() => {
  try {
    setLoading(true)(async () => {
      const data = await (await fetch(`${API_BASE_URL}/data`)).json();
      setData(data);
    })();
  } catch (error) {
    setError(error);
  } finally {
    setLoading(false);
  }
}, []);

Here is the article link if you want to read

Wahab Shah
  • 2,066
  • 1
  • 14
  • 19