Module
Halogen.Hooks.Extra.Hooks.UseEvent
- Package
- purescript-halogen-hooks-extra
- Repository
- jordanmartinez/purescript-halogen-hooks-extra
#useEvent Source
useEvent :: forall m a. MonadEffect m => Hook m (UseEvent m a) (UseEventApi m a)
Allows you to "push" events that occur inside a hook to a single handler outside of the hook. This allows the end user to use the full API returned by the hook when handling the event. Moreover, the end-user can set up resources on the first time the handler is run and unsubscribe when the finalizer is run.
For example...
-- let's say this is the end-user's Hook code
onEvent <- useEvent
-- Here, we'll inline the code for a hypothetical hook we found.
-- This could be a hook provided by a library or something.
{ foo } <- Hooks.do
-- somewhere in the hypothetical hook, an event occurs
onEvent.push "user clicked foo"
-- return the value of the hook provided by the library
pure { foo: "foo" }
Hooks.useLifecycleEffect do
unsubscribe <- onEvent.setCallback $ Just \setupSubscription str -> do
-- handle the event
Hooks.raise ("Event occurred: " <> str)
setupSubscription do
-- Then, set up some resources in this code block
-- that need to be cleaned up later
liftEffect $ log $ "Setting up resources."
pure do
-- now define the code that will run when we call
-- 'unsubscribe' later
liftEffect $ log $ "Cleaning up resources."
pure $ Just do
-- unsubscribe to clean up resources
unsubscribe
If you don't need to unsubscribe, just ignore the first argument
in the function passed to onEvent
:
state /\ stateId <- useState 0
Hooks.captures { state } Hooks.useTickEffect do
-- Notice two things here:
-- 1. we're ignoring the 'unsubscribeCallback' argument
-- by using the underscore (i.e. _).
-- 2. we're ignoring the returned 'unsubscribe' code by using `void`.
void $ onEvent \_ string -> do
-- handle the event
Hooks.raise ("Event occurred: " <> string)
pure Nothing -- no need to unsubscribe here
Beware Infinite Loops
If you use this hook, it's possible for you to create an infinite loop. This will occur if a handler runs code that causes another event to be emitted. Consider this workflow:
- Event A is emitted
- During A's handler, Action X is called
- During Action X's computation, Event A is emitted.
- An infinite loop occurs (go to Step 2)
Here's an example in code:
library <- useLibrary
useLifecycleEffect do
library.onNewInteger \newInt -> do
library.setIntValue (newInt + 1)
Consider also cases where the chain is longer and some computations run only when certain conditions are true:
- Event A is emitted
- During A's handler, Action X is called
- During Action X's computation, Event B is emitted.
- During B's handler, Action Y is called
- During Action Y's computation, Event C is emitted but only if State M is equal to 4.
- During C's handler, Action Z is called
- During Action Z's computation, Event A is emitted.
- Infinite loop may occur (depends on State M)