kee
kee

Reputation: 61

Can I fetch() multiple times in a loader function and extract it with one useloaderdata()?

ive been watching people use useLoaderData() to extract the values that been passed to the react component

Here's my code in App.js,

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route path='/' element={<RootLayout/>}>
      
      <Route path='user' loader={userLoader} element={<User/>}></Route>
      
    </Route>
  )
)

In element,

import { useLoaderData, Link } from "react-router-dom";

const User = () => {

    const users = useLoaderData();

    return (
        <div >
        </div>
    );


}

//loader function
export const userLoader = async () => {

    const res = await fetch('http://localhost:8000/user');
    return res.json();
}

export default User;

My question is, isit possible to fetch from multiple URL and return once to the browser and extract with useLoaderData()?

which something looks like this

export const userLoader = async () => {
    const res1 = await fetch('http://localhost:8000/user');
    const user= res1.json();
    const res2 = await fetch('http://localhost:8000/car');
    const car= res2.json();

    return {user, car};    
}

i had tried above code and it returns a weird promise

and i noticed whenever i surround the json result with {} in loader function it returns a promise, why is it so?


//loader function
export const userLoader = async () => {

    const res = await fetch('http://localhost:8000/user');
    return {res.json()}; ////why u cant put {}?
}

export default User;

Upvotes: 3

Views: 1973

Answers (1)

Drew Reese
Drew Reese

Reputation: 203373

The curly brackets only define a scope or object literal, it's the function being declared async that makes it implicitly return a Promise object. The useLoaderData hook and RRD Data router do the awaiting. When you use the following

export const userLoader = async () => {
  const res1 = await fetch('http://localhost:8000/user');
  const user = res1.json();
  const res2 = await fetch('http://localhost:8000/car');
  const car = res2.json();

  return { user, car };    
}

The code is resolving the implicit return with an object with properties user and car that are themselves unresolved Promise objects, e.g. res.json() returns a Promise.

The loader should await the JSON Promises as well.

export const userLoader = async () => {
  const res1 = await fetch('http://localhost:8000/user');
  const user = await res1.json();
  const res2 = await fetch('http://localhost:8000/car');
  const car = await res2.json();

  return { user, car };    
}

If none of these fetch requests are dependent on any other previous request resolving then you can speed things up a little bit by fetching things concurrently using Promise.all.

Example:

export const userLoader = async () => {
  const [user, car] = await Promise.all([
    fetch('http://localhost:8000/user').then(res => res.json()),
    fetch('http://localhost:8000/car').then(res => res.json()),
  ]);

  return { user, car };    
}

Upvotes: 7

Related Questions