swr-site icon indicating copy to clipboard operation
swr-site copied to clipboard

provider: localStorageProvider with Typescript

Open ghost opened this issue 2 years ago • 4 comments

ghost avatar Jan 09 '23 00:01 ghost

<SWRConfig value={{ provider: localStorageProvider }} > but show this error: (property) provider?: ((cache: Readonly<Cache>) => Cache) | undefined Type '() => Map<unknown, unknown>' is not assignable to type '(cache: Readonly<Cache>) => Cache'. Call signature return types 'Map<unknown, unknown>' and 'Cache' are incompatible. The types returned by 'keys()' are incompatible between these types. Type 'IterableIterator' is not assignable to type 'IterableIterator'. Type 'unknown' is not assignable to type 'string'

ghost avatar Jan 09 '23 00:01 ghost

import { Suspense, useEffect } from 'react'; import './App.css' import { fetchRickAndMorty, rickAndMortyUrl } from './services/rickAndMorty'; import useSWR, { SWRConfig } from 'swr';

import Skeleton from '@mui/material/Skeleton'

function localStorageProvider(){ // When initializing, we restore the data from localStorage into a map. const map = new Map(JSON.parse(localStorage.getItem('gentelman-cache') || '[]'))

// Before unloading the app, we write back all the data into localStorage. window.addEventListener('beforeunload', () => { const appCache = JSON.stringify(Array.from(map.entries())) localStorage.setItem('gentelman-cache', appCache) })

// We still use the map for write & read for performance. return map }

interface ICharacter { id: number; name: string; }

function App() {

const { data, error } = useSWR(rickAndMortyUrl, fetchRickAndMorty, { suspense: true, revalidateIfStale: false, revalidateOnFocus: false, })

useEffect(() => {

}, [])

return ( <SWRConfig value={{ provider: localStorageProvider }} > <Suspense fallback={ <> <Skeleton variant="text" sx={{ fontSize: '1rem' }} /> <Skeleton variant="circular" width={40} height={40} /> <Skeleton variant="rectangular" width={210} height={60} /> <Skeleton variant="rounded" width={210} height={60} /> </> }> <div className="App"> DATA: {data.results.map((character: ICharacter) => (

{character.name}
))} </Suspense> </SWRConfig> ) }

export default App

ghost avatar Jan 09 '23 00:01 ghost

I fixed this issue by providing the correct type when instantiating the Map in the provider function.

const map = new Map<string, unknown>(JSON.parse(localStorage.getItem(KEY) || '[]'))

bflemi3 avatar Nov 08 '23 13:11 bflemi3

For me this worked.:

function localStorageProvider() {
    // When initializing, we restore the data from `localStorage` into a map.
    const map = new Map<string, object>(
        JSON.parse(localStorage.getItem('app-cache') || '[]')
    )

    // Before unloading the app, we write back all the data into `localStorage`.
    window.addEventListener('beforeunload', () => {
        const appCache = JSON.stringify(Array.from(map.entries()))
        localStorage.setItem('app-cache', appCache)
    })

    // We still use the map for write & read for performance.
    return map
}

dacgray avatar Apr 18 '24 09:04 dacgray