Next.js Discord

Discord Forum

Is there a better way to fetch?

Answered
Yellowstripe scad posted this in #help-forum
Open in Discord
Avatar
Yellowstripe scadOP
interface Switch {
    id: string;
    switch_name: string;
    videos: string[];
    createdAt: Date;
    ended: boolean;
    accented: number;
    bassy: number;
    bouncy: number;
    buttery: number;
    chirpy: number;
    clacky: number;
    creamy: number;
    crunchy: number;
    easy_to_press: number;
    feathery: number;
    frictionless: number;
    gummy: number;
    high_pitched: number;
    invigorating: number;
    low_pitched: number;
    marbly: number;
    mild: number;
    muted: number;
    neutral: number;
    polished: number;
    resonant: number;
    sharp: number;
    silky: number;
    snappy: number;
    stepped: number;
    stiff: number;
    subdued: number;
    subtle: number;
    textured: number;
    thocky: number;
}
  

export default async function VotePage() {
    let switches;
    try {
        const response = await fetch(process.env.URL + '/api/vote/get_switches', {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            }
        });

        const data = await response.json();
        switches = data.switches;
    } catch (error) {
        console.error("Error:", error);
    }

    return (
        <div>
            {switches && switches.map((switchItem: Switch) => (
                <p key={switchItem.id}>{switchItem.id}</p>
            ))}
        </div>
    );
}


I was just wondering if I should use useEffect or useState, it works fine but I feel like im missing something to make it better. any suggestions?
Answered by Yellowstripe scad
app/vote/page.tsx
"use client"

import { useState, useEffect } from 'react'
import { Switch } from "@/lib/types";

export default function VotePage() {
    const [foundSwitches, setFoundSwitches] = useState({ switches: [] });
    useEffect(()=> {
        const getData = async () => {
            const query = await fetch("/api/vote/get_switches")
            const response = await query.json()
            console.log("response from API: ", response)
            setFoundSwitches(response)
        }
        getData()
    }, [])
    return (
        <div>
            {foundSwitches.switches.length > 0 ? (
                    foundSwitches.switches.map((switchItem: Switch) => (
                        <p key={switchItem.id}>{switchItem.id}</p>
                    ))
                ) : (
                    <p>No switches found</p>
                )}
        </div>
    )
}


app/api/vote/get_switches
import { db } from "@/lib/db";
import { NextResponse } from "next/server";

export async function GET(req: Request) {
    try {
        const foundSwitches = await db.preVotingSwitches.findMany();

        if (!foundSwitches) {
            return NextResponse.json({ switch: null, message: "No switches found" }, { status: 404 });
        }
        return NextResponse.json({ switches: foundSwitches, message: "All Switches found" }, { status: 200 });
    } catch (error) {
        console.error("Error:", error); // Log the error for debugging
        return NextResponse.json({ message: "Something went wrong!" }, { status: 500 });
    }
}
View full answer

37 Replies

Avatar
Pond loach
Yes, absolutely, you can can call the fetch in function called getSwitchs() inside useEffect to fetch and useState to affect to a variable of type array of switchs
I think it's more correct then using fetch like you've done because if you check the console I bet it is called more then one time
Avatar
Yellowstripe scadOP
thank you so much lmao, brand new to nextjs and dont even know what those two do!
Avatar
Pond loach
Ah okey, so in fact they are hooks basically used in React then as Next.js is a framework based on it you can use them
So useEffect is called once when the page is loaded
useState you probably know a little bit about it it's to manage a state which is a sort of variable
Avatar
Yellowstripe scadOP
I see, my code here loads forever, dont know why. I dont think I ever call the useEffect or something to actually send the request. how can I fix it:

"use client"

import { useState, useEffect } from 'react'
import { Switch } from "@/lib/types";

export default async function VotePage() {
    const [data, setData] = useState(null)
    const [isLoading, setLoading] = useState(true)
    
    useEffect(() => {
        fetch(process.env.URL + '/api/vote/get_switches', {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
        })
        .then((res) => res.json())
        .then((data) => {
            setData(data)
            setLoading(false)
        })
    }, [])
    if (isLoading) return <p>Loading...</p>
      if (!data) return <p>No profile data</p>
    return (
        <div>
          {/* {data &&
            data.switches.map((switchItem: Switch) => (
              <p key={switchItem.id}>{switchItem.id}</p>
            ))} */}
            {data && data}
        </div>
      );
}


I was using this to try and do it:
https://nextjs.org/docs/pages/building-your-application/data-fetching/client-side
Avatar
Pond loach
isLoading should be false by default in default value of the useState because it doesn't load by default it's logical
So you have to set it to true before the call to fetch inside useEffect
Also you have a POST method set it to GET
Avatar
Yellowstripe scadOP
thanks
Avatar
Pond loach
Thank me when it is fixed 😉
Avatar
Yellowstripe scadOP
I want it to be post, im fetching data, this is also just loading forever
Image
Avatar
Pond loach
Yeah but POST is for posting data not GETing it
Avatar
Yellowstripe scadOP
I thought get was for displaying pages
/api/vote/get_switches
async function GET(req: Request) {
    try {
        const foundSwitches = await db.preVotingSwitches.findMany();

        if (!foundSwitches) {
            return NextResponse.json({ switch: null, message: "No switches found" }, { status: 404 });
        }

        return NextResponse.json({ switches: foundSwitches, message: "All Switches found" }, { status: 200 });
    } catch (error) {
        console.error("Error:", error); // Log the error for debugging
        return NextResponse.json({ message: "Something went wrong!" }, { status: 500 });
    }
}
/vote/page.tsx
"use client"

import { useState, useEffect } from 'react'
import { Switch } from "@/lib/types";

export default function VotePage() {
    const [data, setData] = useState(null)
    const [isLoading, setLoading] = useState(false)
    
    useEffect(() => {
        setLoading(true)
        fetch(process.env.URL + '/api/vote/get_switches', {
            method: "GET",
            headers: {
                "Content-Type": "application/json"
            },
        })
        .then((res) => res.json())
        .then((data) => {
            setData(data)
            setLoading(false)
        })
    }, [])
    if (isLoading) return <p>Loading...</p>
      if (!data) return <p>No profile data</p>
    return (
        <div>
          {/* {data &&
            data.switches.map((switchItem: Switch) => (
              <p key={switchItem.id}>{switchItem.id}</p>
            ))} */}
            {data && data}
        </div>
      );
}
Avatar
Pond loach
try it like this it seems okey
Avatar
Yellowstripe scadOP
it just says "Loading..." forever
Avatar
Pond loach
Try to put setLoading(false) just after the call
"use client"

import { useState, useEffect } from 'react'
import { Switch } from "@/lib/types";

export default function VotePage() {
    const [data, setData] = useState(null)
    const [isLoading, setLoading] = useState(false)
    
    useEffect(() => {
        setLoading(true)
        fetch(process.env.URL + '/api/vote/get_switches', {
            method: "GET",
            headers: {
                "Content-Type": "application/json"
            },
        })
        .then((res) => res.json())
        .then((data) => {
            setData(data)
        })
        setLoading(false)
    }, [])
    if (isLoading) return <p>Loading...</p>
    if (!data) return <p>No profile data</p>
    return (
        <div>
          {data && data.switches.map((switchItem: Switch) => (
              <p key={switchItem.id}>{switchItem.id}</p>
            ))}
        </div>
    );
}
btw, you'll have an error about the typing of the useState that should be an array of Switchs
Avatar
Yellowstripe scadOP
right now im having a problem with my route, I made it into this:

import { db } from "@/lib/db";
import { NextResponse } from "next/server";

export async function GET(req: Request) {
    try {
        const foundSwitches = await db.preVotingSwitches.findMany();

        if (!foundSwitches) {
            console.log("here 2")
            return NextResponse.json({ switch: null, message: "No switches found" }, { status: 404 });
        }
        console.log("here")
        return NextResponse.json({ switches: foundSwitches, message: "All Switches found" }, { status: 200 });
    } catch (error) {
        console.error("Error:", error); // Log the error for debugging
        return NextResponse.json({ message: "Something went wrong!" }, { status: 500 });
    }
}


but neither of the "here"s get logged
Avatar
Pond loach
So why it was working before ?
Avatar
Yellowstripe scadOP
in the route I changed it to GET
nothing gets returned I think
Avatar
Pond loach
Try to call this endpoint https://jsonplaceholder.typicode.com/users
without GET in the header you see
Like this
https://www.youtube.com/watch?v=GM6Uvp0BWVE
Then if it works we'll try to fix the API part 🙂
Avatar
Pond loach
Also if the API is called inside your Next.js app normally you don't need to provide an url so I don't know if it is in the same project
Avatar
Yellowstripe scadOP
this works, copied down the code
let me try adjusting it to my route
Avatar
Pond loach
So if this works it's cool
I think the problem comes from the call with the url, try to not add the process.env.URL
Avatar
Yellowstripe scadOP
oohhh maybeee
u might be right
I only added that for my nextauth
Avatar
Pond loach
Yeah because it's like an external call to the API
Avatar
Yellowstripe scadOP
ok I've got it all working
had to ask chatgpt to fix it but it only added
useState({ switches: [] }) from useState({})
Avatar
Yellowstripe scadOP
app/vote/page.tsx
"use client"

import { useState, useEffect } from 'react'
import { Switch } from "@/lib/types";

export default function VotePage() {
    const [foundSwitches, setFoundSwitches] = useState({ switches: [] });
    useEffect(()=> {
        const getData = async () => {
            const query = await fetch("/api/vote/get_switches")
            const response = await query.json()
            console.log("response from API: ", response)
            setFoundSwitches(response)
        }
        getData()
    }, [])
    return (
        <div>
            {foundSwitches.switches.length > 0 ? (
                    foundSwitches.switches.map((switchItem: Switch) => (
                        <p key={switchItem.id}>{switchItem.id}</p>
                    ))
                ) : (
                    <p>No switches found</p>
                )}
        </div>
    )
}


app/api/vote/get_switches
import { db } from "@/lib/db";
import { NextResponse } from "next/server";

export async function GET(req: Request) {
    try {
        const foundSwitches = await db.preVotingSwitches.findMany();

        if (!foundSwitches) {
            return NextResponse.json({ switch: null, message: "No switches found" }, { status: 404 });
        }
        return NextResponse.json({ switches: foundSwitches, message: "All Switches found" }, { status: 200 });
    } catch (error) {
        console.error("Error:", error); // Log the error for debugging
        return NextResponse.json({ message: "Something went wrong!" }, { status: 500 });
    }
}
Answer
Avatar
Yellowstripe scadOP
ty!