简体   繁体   中英

How can I use AbortController in Next js?

My application allows users to do searches and get suggestions as they type in the search box. For each time that the user enters a character, I use 'fetch' to fetch the suggestions from an API. The thing is that if the user does the search fast, he can get the result before the suggestions are fetched. In this case, I want to cancel the fetch request.

I used to have the same application in React and I could easily cancel the request using AbortController, but that isn't working in Next.js.

I did some research and I think the problem is happening because Next doesn't have access to AbortController when it tries to generate the pages.

I also had this problem when I tried to use 'window.innerWidth' because it seems Next doesn't have access to 'window' either.

The solution I found was to use 'useEffect'. It worked perfectly when I used it with 'window'.

const [size, setSize] = useState(0)

useEffect(() => {
   setSize(window.innerWidth)
}, [])

But it isn't working when I use AbortController. First I did it like this:

let suggestionsController;
useEffect(() => {
   suggestionsController  = new AbortController();
},[])

But when I tried to use 'suggestionsController', it would always be undefined.

So I tried to do the same thing using 'useRef'.

const suggestionsControllerRef = useRef(null)
useEffect(() => {
   suggestionsControllerRef.current = new AbortController();
},[])

This is how I'm fetching the suggestions:

async function fetchSuggestions (input){
   try {
      const response = await fetch(`url/${input}`, {signal: suggestionsControllerRef.current.signal})
      const result = await response.json()
      setSuggestionsList(result)
   } catch (e) {
      console.log(e)
   }
}

And this is how I'm aborting the request:

function handleSearch(word) {
    suggestionsControllerRef.current.abort()
    router.push(`/dictionary/${word}`)
    setShowSuggestions(false)
}

Everything works perfectly for the first time. But if the user tries to do another search, 'fetchSuggestions' function stops working and I get this error in the console 'DOMException: Failed to execute 'fetch' on 'Window': The user aborted a request'.

Does anyone know what is the correct way to use AbortController in Next.js?

The solution I found to the problem was create a new instance of AbortController each time that the user does the search. While the suggestions were being displayed, 'showSuggestions' was true, but when 'handleSearch' was called, 'showSuggestions' was set to false. So I just added it as a dependency to useEffect.

useEffect(() => {
   const obj = new AbortController();
   setSuggestionController(obj)
},[showSuggestions])

I also switched from useRef to useState, but I'm not sure if that was necessary because I didn't test this solution with useRef.

I don't know if that is the best way of using AbortController in Next js, but my application is working as expected now.

I suppose you can try an abort controller to cancel your requests if the user stops typing, but this is not the standard way of solving this common problem.

You want to "debounce" the callback that runs when the user types. Debouncing is a strategy that essentially captures the function calls and "waits" a certain amount of time before executing a function. For example, in this case you might want to debounce your search function so that it will only run ONCE, 500 ms after the user has stopped typing, rather than running on every single keypress.

Look into debouncing libraries or write a debounce function yourself, but fair warning it can be pretty tricky at first!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM