Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
142
Issues
142
List
Board
Labels
Milestones
Merge Requests
4
Merge Requests
4
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
purescript-gargantext
Commits
613a0217
Commit
613a0217
authored
Aug 10, 2021
by
Przemyslaw Kaminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[loader] useCacheWithAPI loader with errorHandler
parent
fe2bbca3
Pipeline
#1707
failed with stage
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
80 additions
and
94 deletions
+80
-94
NgramsTable.purs
src/Gargantext/Components/NgramsTable.purs
+62
-78
Loader.purs
src/Gargantext/Components/NgramsTable/Loader.purs
+18
-12
Loader.purs
src/Gargantext/Hooks/Loader.purs
+0
-4
No files found.
src/Gargantext/Components/NgramsTable.purs
View file @
613a0217
...
@@ -7,14 +7,13 @@ module Gargantext.Components.NgramsTable
...
@@ -7,14 +7,13 @@ module Gargantext.Components.NgramsTable
import Gargantext.Prelude
import Gargantext.Prelude
import Data.Array as A
import Data.Array as A
import Data.Either (Either
(..)
)
import Data.Either (Either)
import Data.FunctorWithIndex (mapWithIndex)
import Data.FunctorWithIndex (mapWithIndex)
import Data.Lens (Lens', to, (%~), (.~), (^.), (^?), view)
import Data.Lens (Lens', to, (%~), (.~), (^.), (^?), view)
import Data.Lens.At (at)
import Data.Lens.At (at)
import Data.Lens.Common (_Just)
import Data.Lens.Common (_Just)
import Data.Lens.Fold (folded)
import Data.Lens.Fold (folded)
import Data.Lens.Index (ix)
import Data.Lens.Index (ix)
import Data.Lens.Record (prop)
import Data.Map (Map)
import Data.Map (Map)
import Data.Map as Map
import Data.Map as Map
import Data.Maybe (Maybe(..), fromMaybe, isNothing, maybe)
import Data.Maybe (Maybe(..), fromMaybe, isNothing, maybe)
...
@@ -23,11 +22,15 @@ import Data.Ord.Down (Down(..))
...
@@ -23,11 +22,15 @@ import Data.Ord.Down (Down(..))
import Data.Sequence (Seq, length) as Seq
import Data.Sequence (Seq, length) as Seq
import Data.Set (Set)
import Data.Set (Set)
import Data.Set as Set
import Data.Set as Set
import Data.Symbol (SProxy(..))
import Data.Tuple (Tuple(..))
import Data.Tuple (Tuple(..), fst)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect (Effect)
import Effect.Aff (Aff)
import Effect.Aff (Aff)
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Unsafe.Coerce (unsafeCoerce)
import Gargantext.AsyncTasks as GAT
import Gargantext.AsyncTasks as GAT
import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.NgramsTable.Components as NTC
import Gargantext.Components.NgramsTable.Components as NTC
...
@@ -37,7 +40,7 @@ import Gargantext.Components.Nodes.Lists.Types as NT
...
@@ -37,7 +40,7 @@ import Gargantext.Components.Nodes.Lists.Types as NT
import Gargantext.Components.Table as TT
import Gargantext.Components.Table as TT
import Gargantext.Components.Table.Types as TT
import Gargantext.Components.Table.Types as TT
import Gargantext.Config.REST (RESTError)
import Gargantext.Config.REST (RESTError)
import Gargantext.Hooks.Loader (
loader,
useLoader)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes (SessionRoute(..)) as R
import Gargantext.Routes (SessionRoute(..)) as R
import Gargantext.Sessions (Session, get)
import Gargantext.Sessions (Session, get)
import Gargantext.Types (CTabNgramType, OrderBy(..), SearchQuery, TabType, TermList(..), TermSize, termLists, termSizes)
import Gargantext.Types (CTabNgramType, OrderBy(..), SearchQuery, TabType, TermList(..), TermSize, termLists, termSizes)
...
@@ -46,20 +49,10 @@ import Gargantext.Utils.CacheAPI as GUC
...
@@ -46,20 +49,10 @@ import Gargantext.Utils.CacheAPI as GUC
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Seq as Seq
import Gargantext.Utils.Seq as Seq
import Gargantext.Utils.Toestand as T2
import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
import Unsafe.Coerce (unsafeCoerce)
here :: R2.Here
here :: R2.Here
here = R2.here "Gargantext.Components.NgramsTable"
here = R2.here "Gargantext.Components.NgramsTable"
_ngramsChildren :: forall row. Lens' { ngramsChildren :: Map NgramsTerm Boolean | row } (Map NgramsTerm Boolean)
_ngramsChildren = prop (SProxy :: SProxy "ngramsChildren")
_ngramsSelection :: forall row. Lens' { ngramsSelection :: Set NgramsTerm | row } (Set NgramsTerm)
_ngramsSelection = prop (SProxy :: SProxy "ngramsSelection")
type State =
type State =
CoreState (
CoreState (
ngramsChildren :: Map NgramsTerm Boolean
ngramsChildren :: Map NgramsTerm Boolean
...
@@ -278,27 +271,25 @@ loadedNgramsTable :: R2.Component Props
...
@@ -278,27 +271,25 @@ loadedNgramsTable :: R2.Component Props
loadedNgramsTable = R.createElement loadedNgramsTableCpt
loadedNgramsTable = R.createElement loadedNgramsTableCpt
loadedNgramsTableCpt :: R.Component Props
loadedNgramsTableCpt :: R.Component Props
loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
cpt
props@
{ afterSync
cpt { afterSync
, cacheState
, cacheState
, mTotalRows
, mTotalRows
, path
, path
, reloadForest
, reloadForest
, reloadRoot
, reloadRoot
, state
, state
, tabNgramType
, tabNgramType
, tasks
, tasks
, versioned: Versioned { data: initTable }
, versioned: Versioned { data: initTable }
, withAutoUpdate } _ = do
, withAutoUpdate } _ = do
state'@{ ngramsChildren, ngramsLocalPatch, ngramsParent, ngramsSelection
, ngramsVersion
} <- T.useLive T.unequal state
state'@{ ngramsChildren, ngramsLocalPatch, ngramsParent, ngramsSelection } <- T.useLive T.unequal state
path'@{
listIds, params,
scoreType, termListFilter, termSizeFilter } <- T.useLive T.unequal path
path'@{ scoreType, termListFilter, termSizeFilter } <- T.useLive T.unequal path
params <- T.useFocused (_.params) (\a b -> b { params = a }) path
params <- T.useFocused (_.params) (\a b -> b { params = a }) path
params'@{ orderBy } <- T.useLive T.unequal params
params'@{ orderBy } <- T.useLive T.unequal params
searchQuery <- T.useFocused (_.searchQuery) (\a b -> b { searchQuery = a }) path
searchQuery <- T.useFocused (_.searchQuery) (\a b -> b { searchQuery = a }) path
searchQuery' <- T.useLive T.unequal searchQuery
searchQuery' <- T.useLive T.unequal searchQuery
let ngramsTable = applyNgramsPatches state' initTable
let ngramsTable = applyNgramsPatches state' initTable
roots = rootsOf ngramsTable
rowMap (Tuple ng nre) =
rowMap (Tuple ng nre) =
let ng_scores :: Map NgramsTerm (Additive Int)
let ng_scores :: Map NgramsTerm (Additive Int)
ng_scores = ngramsTable ^. _NgramsTable <<< _ngrams_scores
ng_scores = ngramsTable ^. _NgramsTable <<< _ngrams_scores
...
@@ -317,7 +308,6 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
...
@@ -317,7 +308,6 @@ loadedNgramsTableCpt = here.component "loadedNgramsTable" cpt where
rowsFilter ngramsElement =
rowsFilter ngramsElement =
if displayRow { ngramsElement
if displayRow { ngramsElement
, ngramsParentRoot
, ngramsParentRoot
, ngramsTable
, searchQuery: searchQuery'
, searchQuery: searchQuery'
, state: state'
, state: state'
, termListFilter
, termListFilter
...
@@ -477,17 +467,15 @@ mkDispatch { filteredRows
...
@@ -477,17 +467,15 @@ mkDispatch { filteredRows
displayRow :: { ngramsElement :: NgramsElement
displayRow :: { ngramsElement :: NgramsElement
, ngramsParentRoot :: Maybe NgramsTerm
, ngramsParentRoot :: Maybe NgramsTerm
, ngramsTable :: NgramsTable
, searchQuery :: SearchQuery
, searchQuery :: SearchQuery
, state :: State
, state :: State
, termListFilter :: Maybe TermList
, termListFilter :: Maybe TermList
, termSizeFilter :: Maybe TermSize } -> Boolean
, termSizeFilter :: Maybe TermSize } -> Boolean
displayRow { ngramsElement: NgramsElement {ngrams, root, list}
displayRow { ngramsElement: NgramsElement {ngrams, root, list}
, ngramsParentRoot
, ngramsParentRoot
, ngramsTable
, state: { ngramsChildren
, state: state@{ ngramsChildren
, ngramsLocalPatch
, ngramsLocalPatch
, ngramsParent }
, ngramsParent }
, searchQuery
, searchQuery
, termListFilter
, termListFilter
, termSizeFilter } =
, termSizeFilter } =
...
@@ -535,17 +523,17 @@ mainNgramsTable = R.createElement mainNgramsTableCpt
...
@@ -535,17 +523,17 @@ mainNgramsTable = R.createElement mainNgramsTableCpt
mainNgramsTableCpt :: R.Component MainNgramsTableProps
mainNgramsTableCpt :: R.Component MainNgramsTableProps
mainNgramsTableCpt = here.component "mainNgramsTable" cpt
mainNgramsTableCpt = here.component "mainNgramsTable" cpt
where
where
cpt
props@
{ afterSync
cpt { afterSync
, cacheState
, cacheState
, defaultListId
, defaultListId
, path
, path
, reloadForest
, reloadForest
, reloadRoot
, reloadRoot
, tabNgramType
, tabNgramType
, tasks
, tasks
, withAutoUpdate } _ = do
, withAutoUpdate } _ = do
cacheState' <- T.useLive T.unequal cacheState
cacheState' <- T.useLive T.unequal cacheState
path'
@{ nodeId, tabType, session }
<- T.useLive T.unequal path
path' <- T.useLive T.unequal path
-- let path = initialPageParams session nodeId [defaultListId] tabType
-- let path = initialPageParams session nodeId [defaultListId] tabType
...
@@ -562,6 +550,7 @@ mainNgramsTableCpt = here.component "mainNgramsTable" cpt
...
@@ -562,6 +550,7 @@ mainNgramsTableCpt = here.component "mainNgramsTable" cpt
, withAutoUpdate } []
, withAutoUpdate } []
useLoaderWithCacheAPI {
useLoaderWithCacheAPI {
cacheEndpoint: versionEndpoint { defaultListId, path: path' }
cacheEndpoint: versionEndpoint { defaultListId, path: path' }
, errorHandler
, handleResponse
, handleResponse
, mkRequest
, mkRequest
, path: path'
, path: path'
...
@@ -591,15 +580,15 @@ mainNgramsTableCpt = here.component "mainNgramsTable" cpt
...
@@ -591,15 +580,15 @@ mainNgramsTableCpt = here.component "mainNgramsTable" cpt
-- NOTE With cache off
-- NOTE With cache off
loader :: PageParams -> Aff (Either RESTError VersionedWithCountNgramsTable)
loader :: PageParams -> Aff (Either RESTError VersionedWithCountNgramsTable)
loader
path@
{ listIds
loader { listIds
, nodeId
, nodeId
, params: { limit, offset, orderBy
}
, params: { limit, offset
}
, searchQuery
, searchQuery
, session
, session
, tabType
, tabType
, termListFilter
, termListFilter
, termSizeFilter
, termSizeFilter
} =
} =
get session $ R.GetNgrams params (Just nodeId)
get session $ R.GetNgrams params (Just nodeId)
where
where
params = { limit
params = { limit
...
@@ -618,12 +607,7 @@ mainNgramsTableCpt = here.component "mainNgramsTable" cpt
...
@@ -618,12 +607,7 @@ mainNgramsTableCpt = here.component "mainNgramsTable" cpt
where
where
url { listIds
url { listIds
, nodeId
, nodeId
, params: { limit, offset, orderBy }
, searchQuery
, scoreType
, tabType
, tabType
, termListFilter
, termSizeFilter
} = R.GetNgramsTableAll { listIds
} = R.GetNgramsTableAll { listIds
, tabType } (Just nodeId)
, tabType } (Just nodeId)
...
@@ -643,15 +627,15 @@ mainNgramsTablePaint = R.createElement mainNgramsTablePaintCpt
...
@@ -643,15 +627,15 @@ mainNgramsTablePaint = R.createElement mainNgramsTablePaintCpt
mainNgramsTablePaintCpt :: R.Component MainNgramsTablePaintProps
mainNgramsTablePaintCpt :: R.Component MainNgramsTablePaintProps
mainNgramsTablePaintCpt = here.component "mainNgramsTablePaint" cpt
mainNgramsTablePaintCpt = here.component "mainNgramsTablePaint" cpt
where
where
cpt
props@
{ afterSync
cpt { afterSync
, cacheState
, cacheState
, path
, path
, reloadForest
, reloadForest
, reloadRoot
, reloadRoot
, tabNgramType
, tabNgramType
, tasks
, tasks
, versioned
, versioned
, withAutoUpdate } _ = do
, withAutoUpdate } _ = do
state <- T.useBox $ initialState versioned
state <- T.useBox $ initialState versioned
pure $ loadedNgramsTable { afterSync
pure $ loadedNgramsTable { afterSync
...
@@ -680,15 +664,15 @@ mainNgramsTablePaintNoCache = R.createElement mainNgramsTablePaintNoCacheCpt
...
@@ -680,15 +664,15 @@ mainNgramsTablePaintNoCache = R.createElement mainNgramsTablePaintNoCacheCpt
mainNgramsTablePaintNoCacheCpt :: R.Component MainNgramsTablePaintNoCacheProps
mainNgramsTablePaintNoCacheCpt :: R.Component MainNgramsTablePaintNoCacheProps
mainNgramsTablePaintNoCacheCpt = here.component "mainNgramsTablePaintNoCache" cpt
mainNgramsTablePaintNoCacheCpt = here.component "mainNgramsTablePaintNoCache" cpt
where
where
cpt
props@
{ afterSync
cpt { afterSync
, cacheState
, cacheState
, path
, path
, reloadForest
, reloadForest
, reloadRoot
, reloadRoot
, tabNgramType
, tabNgramType
, tasks
, tasks
, versionedWithCount
, versionedWithCount
, withAutoUpdate } _ = do
, withAutoUpdate } _ = do
let count /\ versioned = toVersioned versionedWithCount
let count /\ versioned = toVersioned versionedWithCount
state <- T.useBox $ initialState versioned
state <- T.useBox $ initialState versioned
...
...
src/Gargantext/Components/NgramsTable/Loader.purs
View file @
613a0217
...
@@ -2,20 +2,21 @@ module Gargantext.Components.NgramsTable.Loader where
...
@@ -2,20 +2,21 @@ module Gargantext.Components.NgramsTable.Loader where
import Gargantext.Prelude
import Gargantext.Prelude
import Affjax (Error(..))
import Data.Either (Either(..))
import Data.Either (Either(..))
import Data.Maybe (Maybe(..), maybe, isJust)
import Data.Maybe (Maybe(..), maybe, isJust)
import Effect (Effect)
import Effect.Aff (Aff, launchAff_, throwError)
import Effect.Aff (Aff, launchAff_, throwError)
import Effect.Class (liftEffect)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Effect.Exception (error)
import Gargantext.Components.LoadingSpinner (loadingSpinner)
import Gargantext.Components.LoadingSpinner (loadingSpinner)
import Gargantext.Components.NgramsTable.Core (Version, Versioned(..))
import Gargantext.Components.NgramsTable.Core (Version, Versioned(..))
import Gargantext.Config.REST (RESTError)
import Gargantext.Config.REST (RESTError
(..)
)
import Gargantext.Utils.CacheAPI as GUC
import Gargantext.Utils.CacheAPI as GUC
import Reactix as R
import Reactix as R
import Simple.JSON as JSON
import Simple.JSON as JSON
import Toestand as T
import Toestand as T
cacheName :: String
cacheName :: String
cacheName = "ngrams-cache-api-loader"
cacheName = "ngrams-cache-api-loader"
...
@@ -25,22 +26,24 @@ clearCache _ = GUC.delete $ GUC.CacheName cacheName
...
@@ -25,22 +26,24 @@ clearCache _ = GUC.delete $ GUC.CacheName cacheName
type LoaderWithCacheAPIProps path res ret = (
type LoaderWithCacheAPIProps path res ret = (
cacheEndpoint :: path -> Aff (Either RESTError Version)
cacheEndpoint :: path -> Aff (Either RESTError Version)
, errorHandler :: RESTError -> Effect Unit
, handleResponse :: Versioned res -> ret
, handleResponse :: Versioned res -> ret
, mkRequest :: path -> GUC.Request
, mkRequest
:: path -> GUC.Request
, path :: path
, path
:: path
, renderer :: ret -> R.Element
, renderer
:: ret -> R.Element
)
)
useLoaderWithCacheAPI :: forall path res ret. Eq path => JSON.ReadForeign res => Eq ret =>
useLoaderWithCacheAPI :: forall path res ret. Eq path => JSON.ReadForeign res => Eq ret =>
Record (LoaderWithCacheAPIProps path res ret)
Record (LoaderWithCacheAPIProps path res ret)
-> R.Hooks R.Element
-> R.Hooks R.Element
useLoaderWithCacheAPI { cacheEndpoint, handleResponse, mkRequest, path, renderer } = do
useLoaderWithCacheAPI { cacheEndpoint,
errorHandler,
handleResponse, mkRequest, path, renderer } = do
state <- T.useBox Nothing
state <- T.useBox Nothing
state' <- T.useLive T.unequal state
state' <- T.useLive T.unequal state
useCachedAPILoaderEffect { cacheEndpoint
useCachedAPILoaderEffect { cacheEndpoint
, errorHandler
, handleResponse
, handleResponse
, mkRequest
, mkRequest
, path
, path
...
@@ -49,6 +52,7 @@ useLoaderWithCacheAPI { cacheEndpoint, handleResponse, mkRequest, path, renderer
...
@@ -49,6 +52,7 @@ useLoaderWithCacheAPI { cacheEndpoint, handleResponse, mkRequest, path, renderer
type LoaderWithCacheAPIEffectProps path res ret = (
type LoaderWithCacheAPIEffectProps path res ret = (
cacheEndpoint :: path -> Aff (Either RESTError Version)
cacheEndpoint :: path -> Aff (Either RESTError Version)
, errorHandler :: RESTError -> Effect Unit
, handleResponse :: Versioned res -> ret
, handleResponse :: Versioned res -> ret
, mkRequest :: path -> GUC.Request
, mkRequest :: path -> GUC.Request
, path :: path
, path :: path
...
@@ -59,6 +63,7 @@ useCachedAPILoaderEffect :: forall path res ret. Eq path => JSON.ReadForeign res
...
@@ -59,6 +63,7 @@ useCachedAPILoaderEffect :: forall path res ret. Eq path => JSON.ReadForeign res
Record (LoaderWithCacheAPIEffectProps path res ret)
Record (LoaderWithCacheAPIEffectProps path res ret)
-> R.Hooks Unit
-> R.Hooks Unit
useCachedAPILoaderEffect { cacheEndpoint
useCachedAPILoaderEffect { cacheEndpoint
, errorHandler
, handleResponse
, handleResponse
, mkRequest
, mkRequest
, path
, path
...
@@ -77,10 +82,10 @@ useCachedAPILoaderEffect { cacheEndpoint
...
@@ -77,10 +82,10 @@ useCachedAPILoaderEffect { cacheEndpoint
launchAff_ $ do
launchAff_ $ do
cache <- GUC.openCache $ GUC.CacheName cacheName
cache <- GUC.openCache $ GUC.CacheName cacheName
-- TODO Parallelize?
-- TODO Parallelize?
vr@(Versioned { version
, "data": d
}) <- GUC.cachedJson cache req
vr@(Versioned { version }) <- GUC.cachedJson cache req
eCacheReal <- cacheEndpoint path
eCacheReal <- cacheEndpoint path
case eCacheReal of
case eCacheReal of
Left err ->
throwError $ error $ "[useCachedAPILoaderEffect] RESTError"
Left err ->
liftEffect $ errorHandler err
Right cacheReal -> do
Right cacheReal -> do
val <- if version == cacheReal then
val <- if version == cacheReal then
pure vr
pure vr
...
@@ -92,8 +97,9 @@ useCachedAPILoaderEffect { cacheEndpoint
...
@@ -92,8 +97,9 @@ useCachedAPILoaderEffect { cacheEndpoint
_ <- GUC.deleteReq cache req
_ <- GUC.deleteReq cache req
vr'@(Versioned { version: version', data: _ }) <- GUC.cachedJson cache req
vr'@(Versioned { version: version', data: _ }) <- GUC.cachedJson cache req
if version' == cacheReal then
if version' == cacheReal then
pure vr'
pure vr'
else
else do
throwError $ error $ "[useCachedAPILoaderEffect] Fetched clean cache but hashes don't match: " <> show version <> " != " <> show cacheReal
liftEffect $ errorHandler $ SendResponseError $ RequestContentError $ "[useCachedAPILoaderEffect] Fetched clean cache but hashes don't match: " <> show version <> " != " <> show cacheReal
throwError $ error $"[useCachedAPILoaderEffect] Fetched clean cache but hashes don't match: " <> show version <> " != " <> show cacheReal
liftEffect $ do
liftEffect $ do
T.write_ (Just $ handleResponse val) state
T.write_ (Just $ handleResponse val) state
src/Gargantext/Hooks/Loader.purs
View file @
613a0217
...
@@ -2,8 +2,6 @@ module Gargantext.Hooks.Loader where
...
@@ -2,8 +2,6 @@ module Gargantext.Hooks.Loader where
import Gargantext.Prelude
import Gargantext.Prelude
import Control.Bind ((=<<))
import Control.Monad.RWS (state)
import Data.Either (Either(..))
import Data.Either (Either(..))
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..), isJust, maybe)
import Data.Maybe (Maybe(..), isJust, maybe)
...
@@ -13,7 +11,6 @@ import Effect.Aff (Aff, launchAff_, throwError)
...
@@ -13,7 +11,6 @@ import Effect.Aff (Aff, launchAff_, throwError)
import Effect.Class (liftEffect)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Effect.Exception (error)
import Reactix as R
import Reactix as R
import Record as Record
import Simple.JSON as JSON
import Simple.JSON as JSON
import Toestand as T
import Toestand as T
...
@@ -106,7 +103,6 @@ type LoaderWithCacheAPIProps path res ret = (
...
@@ -106,7 +103,6 @@ type LoaderWithCacheAPIProps path res ret = (
, renderer :: ret -> R.Element
, renderer :: ret -> R.Element
)
)
useLoaderWithCacheAPI :: forall path res ret.
useLoaderWithCacheAPI :: forall path res ret.
Eq ret => Eq path => JSON.ReadForeign res =>
Eq ret => Eq path => JSON.ReadForeign res =>
Record (LoaderWithCacheAPIProps path res ret)
Record (LoaderWithCacheAPIProps path res ret)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment