Problem with debouncing mechanism with nextjs 14

103 views Asked by At

I'm working with the fake api jsonplaceholder. I'm listing posts and trying to filter them by userID changing the endpoint. To avoid hitting the api many times, I wanted to make a debounce mechanism. I'm using a dynamic url which changes when the user inputs and ID in a number input. For fetching data i'm using the hook useSWR, and for revalidating the data when the user wants to filter it, I'm using the mutate characteristic of SWR.

The debounced mechanism works well but the only problem is one character delayed. For example, if the user types the ID 11, it only takes 1. The first user input doesn't make any effect for this.

Any idea of how can I solve this?

The code:

'use client'

import { useEffect, useState } from "react";
import Cards from "../components/Cards";
import useSWR, { useSWRConfig } from "swr";
import { useDebounce } from 'use-debounce';

const fetcher = async (url: string) => {
    const res = await fetch(url)
    const data = await res.json()
    return data
}


export default function Page(){
    const [val, setVal] = useState("")
    const [url, setUrl] = useState('https://jsonplaceholder.typicode.com/posts');
    const [debounced] = useDebounce(val, 1000)

    const {data, error} = useSWR('/posts', () => fetcher(url))
    const { mutate } = useSWRConfig()
    
    const change = (event: any) => {
        setVal(event.target.value)
        if(val != '') setUrl(`https://jsonplaceholder.typicode.com/posts?userId=${Number(val)}`)
        else setUrl('https://jsonplaceholder.typicode.com/posts')
    }
    
    useEffect(() => {
        mutate('/posts')
        console.log(url)    
    }, [debounced])

The code continues but it's just how I handle some errors and the HTML Code.

Thanks!!

I tried to make a debounce mechanism to avoid hitting the api unnecessary times for resource optimization.

1

There are 1 answers

0
Hashan Hemachandra On

Your useDebounce hook is correctly delaying the update of debounced, but the URL is being updated immediately upon user input in the change event handler. Because of this, the useEffect that triggers the mutate function is using the debounced value, but the URL gets updated before the debounce effect applies, leading to the one-character delay issue.

You should update the URL based on the debounced value instead of the immediate value from the user input. Remove the URL setting part from the change handler, since you want this to happen after the debounce. Use another useEffect to update the URL whenever the debounced value changes.

// Remove URL update from here
const change = (event: any) => {
    setVal(event.target.value)
}

// Add a new useEffect to handle URL updates based on the debounced value
useEffect(() => {
    if(debounced !== '') setUrl(`https://jsonplaceholder.typicode.com/posts?userId=${Number(debounced)}`)
    else setUrl('https://jsonplaceholder.typicode.com/posts')
}, [debounced]);

// Existing useEffect for data fetching
useEffect(() => {
    mutate('/posts')
    console.log(url)    
}, [url]); // Change this dependency to url instead of debounced