skip to Main Content

I’ve created a route handler using the new app router to do a GET (get all) and retrieved the data into the client which I can see in my console. How can I now display this data in NextJS v13.4?

Here is how I created my route handler which calls a database:

//  /app/api/tacos/routes.js

import { NextRequest, NextResponse } from ‘next/server’;
import { supabaseClient } from ‘../../supabaseClient’;

export async function GET () {    
  try {    
    const { data, error } = supabaseClient.from(‘my_table’).select(*);

    if (error) {
    return NextResponse.json({error: ‘Error in getting the tacos from Supabase.’}, {status: 500})
  }
    return NextResponse.json({data}, {status: 200}); 
  }
  catch (error) {
    return NextResponse.json({message: ‘Error in getting the tacos from the API.’}, {status: 500});
  }
}

Here is how I called the route handler:

const getAllTacos = async () => {
  const response = await fetch(‘/api/tacos’, {
    method: ‘GET’
  });

  if(response.ok) {
    const { data } = await response.json();
    console.log(data);  
    return data;
  } else {
    throw New Error (‘Error on getAllTacos’);
  }
}

As part of my testing, I created a button that lets me retrieve the data which I can see in the console.

return (
  <div className=“button bg-yellow-500” onClick={getAllTacos}>Get All Tacos</div>
)

but how can I now call this route handler so that the user sees this when the page loads?

2

Answers


  1. Chosen as BEST ANSWER

    You’re almost there. Now you simply need to automatically make that call so that the user sees this before the page loads.

    Simplest way? useEffect to call the route handler that you’ve already defined.

    In the useEffect’s dependency array put an empty array so that it triggers only on the first load like this useEffect(()=> {…}, []); This is similar to doing it on React’s componentDidMount (previous way of doing it).

    So it would look like this:

    useEffect(()=> {
      const fetchAndSetTacosArray = async () => {
    
      try {
        const returnedTacoData = await getAllTacos();
        setTacoArray(returnedTacoData};
      } catch (error) {
        console.error(‘Error fetching taco data’, error);
      }
    
      fetchAndSetTacosArray();
    }, []);
    

    Quick note: the reason why there is this intermediate async fetchAndSetTacosArray is that you need an await keyword. The await requires an async function and useEffect cannot be async so you have to put the async function within.

    Second: Create a state variable on your page that will locally hold the returned data from your database const [tacoData, setTacoData] = useState([]);

    Third: Map out the items of the array to display the items

    <div>tacoArray.map((item, index)=>(<div key={index}>{taco.name} {taco.price} {taco.calories}</div>)</div>
    

    Ps. Don't worry ... taco.calories would never be included in this app =) Just making sure you’re still paying attention.

    So together it would look like this:

    // /app/MyTacoPage.js
    
    import React, { useState, useEffect } from 'react';
    
    export default function Page(props) {
      const [tacoArray, setTacoArray] = useState([]);
    
      useEffect(()=> { 
    
        const fetchAndSetTacosArray = async () => {
    
        try {
          const returnedTacoData = await getAllTacos();
          setTacoArray(returnedTacoData};
        } catch (error) {
          console.error(‘Error fetching taco data’, error);
        }
    
        fetchAndSetTacosArray();
        }, []);
    
      const getAllTacos = async () => {
        const response = await fetch(‘/api/tacos’, {
          method: ‘GET’
        });
    
        if(response.ok) {
          const { data } = await response.json();
          console.log(data);  
          return data;
        } else {
          throw New Error (‘Error on getAllTacos’);
        }
      };
    
      return (
      <div className=“w-screen h-screen bg-slate-300>
        <div>tacoArray.map((item, index)=>(<div key={index}>{taco.name} {taco.price} {taco.calories}</div>)</div>
      </div>
      )
    };
    

  2. If you want to get fancy and use Vercel’s swr to handle data retrieving, can you do so like this.

    // /app/MyTacoPage.js
    
    import React from 'react';
    import useSWR from 'swr'
    
    const fetcher = (...args) => fetch(...args).then(res => res.json())
    
    export default function Page(props) {
    
      const { data: tacoArray, error, isLoading } = useSWR('/api/tacos', fetcher)
     
      if (error) return <div>failed to load</div>
      if (isLoading) return <div>loading...</div>
     
      return (
      <div className=“w-screen h-screen bg-slate-300>
        <div>tacoArray.map((item, index)=>(<div key={index}>{taco.name} {taco.price} {taco.calories}</div>)</div>
      </div>
      )
    };
    

    Note when you don’t specify the method, the default is GET. If you need to specify POST for example, you simply replace in the above fetcher with {fetcher, method: POST}

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search