swr
swr copied to clipboard
UseSWR wrapper doesnt override and routes to the wrong fetcher (SWR global config's)
Bug report
Description / Observed Behavior
As the title says, I have a useSharedState hook that is used to pass state between components without prop drilling. This hook is not for http resources, it doesnt have a url fetcher but has an initial state option
import useSWR from 'swr'
export const useSharedState = (key, initial) => {
const { data: state, mutate: setState } = useSWR(key, null, {
fallbackData: initial,
})
return [state, setState]
}
I also have SWR global config in my App.js with its own fetcher
import useSWR, { SWRConfig } from 'swr'
const App = () => {
return (
<React.Fragment>
<SWRConfig
value={{
fetcher: (resource, init) => fetch(`${process.env.REACT_APP_BASE_URL}/api` + resource, init).then(res => res.json())
}}
>
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Routes>
...
When I make an useSWR
call it adds the base url to query endpoints in components
However when I have useSWR
and useSharedState
in the same component or when I call useSharedState
directly, it goes to the wrong fetcher & url endpoint defined thats in SWRConfig
import useSWR from 'swr'
import { useSharedState } from "../../hooks/useSharedState"
...
function Books() {
useEffect(() => {
document.documentElement.className = "inset";
document.body.className = "inset-body";
}, [])
const {data : recentlyAddedBooks } = useSWR('/books/recently_added');
const [searchInput, setSearchInput] = useSharedState('searchInput') // used for getting text from a searchbox
return (...)
it returns
`GET http://localhost:5000/apisearchInput 404 (Not Found)` because its not a resource url
Expected Behavior
Need all SWR calls with resource urls i.e. useSWR('/books')
to follow the global fetcher in <SWRConfig/>
but other SWR wrappers like useSharedState()
that is not meant for API calls should not use global fetcher option
What am I doing wrong, do I need to fix the hook param to override fetcher?
Repro Steps / Code Example
Additional Context
swr version "^1.3.0",
@ridhwaans
Thank you for reporting this.
A workaround for this is to pass fetcher: null
to the useSWR
in useSharedState
. This avoids overriding useSWR
's fetcher function by the global fetcher
option.
import useSWR from 'swr'
export const useSharedState = (key, initial) => {
const { data: state, mutate: setState } = useSWR(key, null, {
fallbackData: initial,
fetcher: null
})
return [state, setState]
}
It might be better to provide a better way for this if we'd like to push out this pattern.
A workaround for this is to pass
fetcher: null
to theuseSWR
.
I have the exact same issue as OP. I was trying to find workarounds myself, such as providing a noop operation () => {}
to the second argument of useSWR
or evaluate permanently to true for isPaused
option. Some (sort of) worked but no solution I came up with was clean. Thank you for your workaround (although it is a bit verbose and not TS-friendly).