From cb6b7381dc743c394b30d3af30df83a93cb22ae5 Mon Sep 17 00:00:00 2001 From: justinwoo <moomoowoo@gmail.com> Date: Sat, 25 Jan 2020 14:16:15 +0200 Subject: [PATCH] fix localstorage hook not being able to synchronously get state --- src/Gargantext/Components/Forest.purs | 15 +++++++++++---- src/Gargantext/Components/Forest/Tree.purs | 5 ++--- src/Gargantext/Utils/Reactix.purs | 20 ++++++-------------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/Gargantext/Components/Forest.purs b/src/Gargantext/Components/Forest.purs index bb2ab810..f758aa05 100644 --- a/src/Gargantext/Components/Forest.purs +++ b/src/Gargantext/Components/Forest.purs @@ -1,14 +1,19 @@ module Gargantext.Components.Forest where +import Gargantext.Prelude + import Data.Array as A import Data.Maybe (Maybe(..)) +import Data.Set (Set) +import Data.Set as Set +import Data.Tuple (fst) import Data.Tuple.Nested ((/\)) import Gargantext.Components.Forest.Tree (treeView) +import Gargantext.Components.Login.Types (TreeId) import Gargantext.Ends (Frontends) import Gargantext.Routes (AppRoute) import Gargantext.Sessions (Session(..), Sessions, unSessions) import Gargantext.Utils.Reactix as R2 -import Prelude (const, pure, ($), (<$>)) import Reactix as R import Reactix.DOM.HTML as H @@ -24,13 +29,15 @@ forest props = R.createElement forestCpt props [] forestCpt :: R.Component Props forestCpt = R.hooksComponent "G.C.Forest.forest" cpt where - cpt {frontends, route, sessions, showLogin } _ = R2.useCache (frontends /\ route /\ sessions) (cpt' showLogin) - cpt' showLogin (frontends /\ route /\ sessions) = + cpt {frontends, route, sessions, showLogin } _ = do + openNodes <- R2.useLocalStorageState R2.openNodesKey (Set.empty :: Set TreeId) + R2.useCache (frontends /\ route /\ sessions /\ fst openNodes) (cpt' openNodes showLogin) + cpt' openNodes showLogin (frontends /\ route /\ sessions /\ openNodesState) = do pure $ R.fragment $ A.cons (plus showLogin) trees where trees = tree <$> unSessions sessions tree s@(Session {treeId}) = - treeView { root: treeId, frontends, mCurrentRoute: Just route, session: s } + treeView { root: treeId, frontends, mCurrentRoute: Just route, session: s, openNodes } plus :: R2.Setter Boolean -> R.Element plus showLogin = diff --git a/src/Gargantext/Components/Forest/Tree.purs b/src/Gargantext/Components/Forest/Tree.purs index d6f0fc57..309e085f 100644 --- a/src/Gargantext/Components/Forest/Tree.purs +++ b/src/Gargantext/Components/Forest/Tree.purs @@ -20,7 +20,6 @@ import Gargantext.Ends (Frontends) import Gargantext.Routes (AppRoute) import Gargantext.Sessions (Session) import Gargantext.Types (AsyncTask(..)) -import Gargantext.Utils.Reactix as R2 import Reactix as R import Reactix.DOM.HTML as H @@ -29,6 +28,7 @@ type Props = ( root :: ID , mCurrentRoute :: Maybe AppRoute , session :: Session , frontends :: Frontends + , openNodes :: R.State (Set TreeId) ) treeView :: Record Props -> R.Element @@ -37,10 +37,9 @@ treeView props = R.createElement treeViewCpt props [] treeViewCpt :: R.Component Props treeViewCpt = R.hooksComponent "G.C.Tree.treeView" cpt where - cpt { root, mCurrentRoute, session, frontends } _children = do + cpt { root, mCurrentRoute, session, frontends, openNodes } _children = do -- NOTE: this is a hack to reload the tree view on demand reload <- R.useState' (0 :: Reload) - openNodes <- R2.useLocalStorageState R2.openNodesKey (Set.empty :: Set TreeId) pure $ treeLoadView { root, mCurrentRoute, session, frontends, openNodes, reload } diff --git a/src/Gargantext/Utils/Reactix.purs b/src/Gargantext/Utils/Reactix.purs index 260a1291..fd5ab9cf 100644 --- a/src/Gargantext/Utils/Reactix.purs +++ b/src/Gargantext/Utils/Reactix.purs @@ -12,9 +12,8 @@ import Data.Argonaut as Argonaut import Data.Argonaut as Json import Data.Argonaut.Core (Json) import Data.Either (hush) -import Data.Foldable (for_) import Data.Function.Uncurried (Fn2, runFn2) -import Data.Maybe (Maybe(..), fromJust) +import Data.Maybe (Maybe(..), fromJust, fromMaybe) import Data.Nullable (Nullable, null, toMaybe) import Data.Tuple (Tuple(..)) import Data.Tuple.Nested ((/\)) @@ -23,6 +22,7 @@ import Effect.Aff (Aff, launchAff, launchAff_, killFiber) import Effect.Class (liftEffect) import Effect.Exception (error) import Effect.Uncurried (EffectFn1, mkEffectFn1, mkEffectFn2, runEffectFn1) +import Effect.Unsafe (unsafePerformEffect) import FFI.Simple ((..), (...), defineProperty, delay, args2, args3) import Partial.Unsafe (unsafePartial) import React (class ReactPropFields, Children, ReactClass, ReactElement) @@ -267,25 +267,17 @@ type LocalStorageKey = String useLocalStorageState :: forall s. Argonaut.DecodeJson s => Argonaut.EncodeJson s => LocalStorageKey -> s -> R.Hooks (R.State s) useLocalStorageState key s = do - ref <- R.useRef s - - R.useEffectOnce' do + -- we need to synchronously get the initial state from local storage + Tuple state setState' <- R.useState \_ -> unsafePerformEffect do item :: Maybe String <- getItem key =<< getls let json = hush <<< Argonaut.jsonParser =<< item let parsed = hush <<< Argonaut.decodeJson =<< json - for_ parsed \(x :: s) -> R.setRef ref x - - let init = R.readRef ref - - Tuple state setState' <- R.useState' init + pure $ fromMaybe s parsed let setState update = do - let new = update (R.readRef ref) - + let new = update state setState' (\_ -> new) - R.setRef ref new - let json = Json.stringify $ Argonaut.encodeJson new storage <- getls setItem key json storage -- 2.21.0