Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-reactix
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
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-reactix
Commits
8df9707e
Commit
8df9707e
authored
Jun 30, 2019
by
James Laver
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Hook changes in preparation for 0.4.0
parent
2634f579
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
96 additions
and
75 deletions
+96
-75
README.md
README.md
+30
-1
Hooks.purs
src/Reactix/Hooks.purs
+55
-64
Spec.purs
test/Reactix/React/Spec.purs
+11
-10
No files found.
README.md
View file @
8df9707e
...
...
@@ -66,7 +66,6 @@ Not in any particular order
1.
Safe DOM props:
*
Make sure each element only takes the correct props
*
Translate some props with minimal and efficient wrapping
2.
Refs
*
Test forwardRef
3.
Context
...
...
@@ -89,6 +88,24 @@ Not in any particular order
<!-- * `R.React.provide` - provider a value through a `Provider` -->
<!-- * `R.React.consume` - consume a value through a `Consumer` -->
### 0.4.0
Breaking:
*
`useState`
now takes a (pure)
`Unit -> s`
initialiser
*
`useState`
's setter function now takes a pure fn
`state -> state`
.
To get back the old behaviour of setting a value without
regard to its existing value, use
`const`
.
*
`useReducer`
now takes a (pure)
`i -> s`
initialiser
*
`useEffect`
,
`useLayoutEffect`
and their numbered variants no longer
take a redundant dummy unit value to delay computation.
### 0.3.1
Bug Fixes:
*
`R.DOM.HTML`
- more or less everything was broken since we moved out
`createDOMElement`
### 0.3.0
Newly supported hooks and variants:
...
...
@@ -109,6 +126,11 @@ Newly supported functions:
*
`R.Hooks.nothing`
- an empty cleanup function
*
`R.Hooks.thenNothing`
- make an effect function return an empty cleanup function
Changes:
*
`R.createDOMElement`
is now how you create DOM elements, we removed
the
`R.IsComponent`
instance for
`String`
Bug Fixes:
*
`R.React.render`
was broken because the tests don't use it and
...
...
@@ -146,6 +168,13 @@ Notable changes:
*
Major refactor to use
[
ffi-simple
](
https://github.com/irresponsible/purescript-ffi-simple
)
.
## Thanks
-
[
Nicolas Pouillard
](
https://github.com/np
)
, for the discussions that
continue to shape the design of reactix.
-
The rest of the
[
gargantext
](
https://gitlab.iscpif.fr/gargantext/purescript-gargantext
)
team, for their enthusiasm both for reactix and for replacing thermite.
## Copyright and License
Copyright (c) 2018 James Laver
...
...
src/Reactix/Hooks.purs
View file @
8df9707e
...
...
@@ -4,7 +4,7 @@ module Reactix.Hooks
, useContext
, useRef
, useDebugValue, useDebugValue'
,
HookEffect,
nothing, thenNothing
, nothing, thenNothing
, useEffect, useEffect', useEffect1, useEffect1'
, useEffect2, useEffect2', useEffect3, useEffect3'
, useEffect4, useEffect4', useEffect5, useEffect5'
...
...
@@ -34,21 +34,23 @@ import FFI.Simple ((...), (..), delay, args2, args3, args4, args5, setProperty)
import FFI.Simple.PseudoArray as Array
import DOM.Simple.Console
import Reactix.Utils (tuple, currySecond, hook)
import Reactix.React (Context, Ref, Hooks, react)
import Reactix.React (Context, Ref, Hooks, react
, unsafeHooksEffect
)
--- useState
-- | A state hook is a tuple of value and setter
type State state = Tuple state (
state
-> Effect Unit)
type State state = Tuple state (
(state -> state)
-> Effect Unit)
-- | Given an Effect function returning an initial value, returns a State
useState :: forall s. (Unit ->
Effect
s) -> Hooks (State s)
useState :: forall s. (Unit -> s) -> Hooks (State s)
useState s =
hook $ \_ ->
pure $ currySecond $ tuple $ react ... "useState" $ [ delay unit
s
]
pure $ currySecond $ tuple $ react ... "useState" $ [ delay unit
(pure <<< s)
]
useState' :: forall s. s -> Hooks (State s)
useState' s = useState $
\_ -> pure
s
useState' s = useState $
const
s
-- useReducer
-- | A reducer hook is a tuple of value and reducer-setter
...
...
@@ -57,15 +59,15 @@ type Reducer state action = Tuple state (action -> Effect Unit)
-- | Given a reducer function from a state and action to a new state,
-- | an initialiser function and argument for the initialiser, returns
-- | a Reducer. Note args 2 and 3 are swapped in order from React.
useReducer :: forall s a i. (s -> a -> s) -> (i ->
Effect
s) -> i -> Hooks (Reducer s a)
useReducer :: forall s a i. (s -> a -> s) -> (i -> s) -> i -> Hooks (Reducer s a)
useReducer f i j =
hook $ \_ ->
pure $ currySecond $ tuple $ react ... "useReducer" $ args3 (mkFn2 f) j
(mkEffectFn1 i)
pure $ currySecond $ tuple $ react ... "useReducer" $ args3 (mkFn2 f) j
i
-- | Like `useReducer`, but takes an initial state instead of an
-- | initialiser function and argument
useReducer' :: forall s a. (s -> a -> s) -> s -> Hooks (Reducer s a)
useReducer' r = useReducer r
pure
useReducer' r = useReducer r
identity
-- useContext
...
...
@@ -88,75 +90,68 @@ useDebugValue' v = hook $ \_ -> pure $ react ... "useDebugValue" $ [v]
-- useEffect
type HookEffect = Unit -> Effect (Unit -> Effect Unit)
-- | A cleanup handler that does nothing
nothing ::
Unit ->
Effect Unit
nothing
_
= pure unit
nothing :: Effect Unit
nothing = pure unit
-- | Turns a simple effect function into an effect function that does
-- | nothing in cleanup after running
thenNothing :: forall a.
(Unit -> Effect a) -> HookEffect
thenNothing e
_ = e unit
*> pure nothing
thenNothing :: forall a.
Effect a -> Effect (Effect Unit)
thenNothing e
= e
*> pure nothing
-- | Given an Effect function which returns a cleanup Effect function,
-- | register an effect to be called after rendering
useEffect ::
HookEffect
-> Hooks Unit
useEffect e = hook $ \_ -> pure $ react ... "useEffect" $ [
wrapEffect e
]
useEffect ::
Effect (Effect Unit)
-> Hooks Unit
useEffect e = hook $ \_ -> pure $ react ... "useEffect" $ [
e
]
-- | Like useEffect, but with a memo value
useEffect1 :: forall a. a ->
HookEffect
-> Hooks Unit
useEffect1 :: forall a. a ->
Effect (Effect Unit)
-> Hooks Unit
useEffect1 a e = _useEffect e [a]
-- | Like useEffect, but with 2 memo values
useEffect2 :: forall a b. a -> b ->
HookEffect
-> Hooks Unit
useEffect2 :: forall a b. a -> b ->
Effect (Effect Unit)
-> Hooks Unit
useEffect2 a b e = _useEffect e $ args2 a b
-- | Like useEffect, but with 3 memo values
useEffect3 :: forall a b c. a -> b -> c ->
HookEffect
-> Hooks Unit
useEffect3 :: forall a b c. a -> b -> c ->
Effect (Effect Unit)
-> Hooks Unit
useEffect3 a b c e = _useEffect e $ args3 a b c
-- | Like useEffect, but with 4 memo values
useEffect4 :: forall a b c d. a -> b -> c -> d ->
HookEffect
-> Hooks Unit
useEffect4 :: forall a b c d. a -> b -> c -> d ->
Effect (Effect Unit)
-> Hooks Unit
useEffect4 a b c d e = _useEffect e $ args4 a b c d
-- | Like useEffect, but with 5 memo values
useEffect5 :: forall a b c d e. a -> b -> c -> d -> e ->
HookEffect
-> Hooks Unit
useEffect5 :: forall a b c d e. a -> b -> c -> d -> e ->
Effect (Effect Unit)
-> Hooks Unit
useEffect5 a b c d f e = _useEffect e $ args5 a b c d f
_useEffect :: forall a.
HookEffect
-> a -> Hooks Unit
_useEffect :: forall a.
Effect (Effect Unit)
-> a -> Hooks Unit
_useEffect e a =
hook $ \_ ->
pure $ react ... "useEffect" $
args2 (wrapEffect e) (Array.from a)
wrapEffect :: HookEffect -> Effect (Effect Unit)
wrapEffect f = delay unit $ \_ -> do
cleanup <- f unit
pure $ delay unit cleanup
args2 e (Array.from a)
-- | Like useEffect, but the provided Effect fn does not return a cleanup handler
useEffect' :: forall a.
(Unit -> Effect a)
-> Hooks Unit
useEffect' :: forall a.
Effect a
-> Hooks Unit
useEffect' = useEffect <<< thenNothing
-- | Like useEffect1, but the provided Effect fn does not return a cleanup handler
useEffect1' :: forall a b. a ->
(Unit -> Effect b)
-> Hooks Unit
useEffect1' :: forall a b. a ->
Effect b
-> Hooks Unit
useEffect1' a = useEffect1 a <<< thenNothing
-- | Like useEffect2, but the provided Effect fn does not return a cleanup handler
useEffect2' :: forall a b c. a -> b ->
(Unit -> Effect c)
-> Hooks Unit
useEffect2' :: forall a b c. a -> b ->
Effect c
-> Hooks Unit
useEffect2' a b = useEffect2 a b <<< thenNothing
-- | Like useEffect3, but the provided Effect fn does not return a cleanup handler
useEffect3' :: forall a b c d. a -> b -> c ->
(Unit -> Effect d)
-> Hooks Unit
useEffect3' :: forall a b c d. a -> b -> c ->
Effect d
-> Hooks Unit
useEffect3' a b c = useEffect3 a b c <<< thenNothing
-- | Like useEffect4, but the provided Effect fn does not return a cleanup handler
useEffect4' :: forall a b c d e. a -> b -> c -> d ->
(Unit -> Effect e)
-> Hooks Unit
useEffect4' :: forall a b c d e. a -> b -> c -> d ->
Effect e
-> Hooks Unit
useEffect4' a b c d = useEffect4 a b c d <<< thenNothing
-- | Like useEffect5, but the provided Effect fn does not return a cleanup handler
useEffect5' :: forall a b c d e f. a -> b -> c -> d -> e ->
(Unit -> Effect f)
-> Hooks Unit
useEffect5' :: forall a b c d e f. a -> b -> c -> d -> e ->
Effect f
-> Hooks Unit
useEffect5' a b c d e = useEffect5 a b c d e <<< thenNothing
-- useLayoutEffect
...
...
@@ -164,62 +159,62 @@ useEffect5' a b c d e = useEffect5 a b c d e <<< thenNothing
-- | Given an Effect function which returns a cleanup Effect function,
-- | register an effect to be called in the same phase as
-- | `componentDidMount` and `componentDidUpdate` used to be.
useLayoutEffect ::
HookEffect
-> Hooks Unit
useLayoutEffect e = hook $ \_ -> pure $ react ... "useLayoutEffect" $ [
wrapEffect
e ]
useLayoutEffect ::
Effect (Effect Unit)
-> Hooks Unit
useLayoutEffect e = hook $ \_ -> pure $ react ... "useLayoutEffect" $ [ e ]
-- | Like useLayoutEffect, but with a memo value
useLayoutEffect1 :: forall a. a ->
HookEffect
-> Hooks Unit
useLayoutEffect1 :: forall a. a ->
Effect (Effect Unit)
-> Hooks Unit
useLayoutEffect1 a e = _useLayoutEffect e [a]
-- | Like useLayoutEffect, but with 2 memo values
useLayoutEffect2 :: forall a b. a -> b ->
HookEffect
-> Hooks Unit
useLayoutEffect2 :: forall a b. a -> b ->
Effect (Effect Unit)
-> Hooks Unit
useLayoutEffect2 a b e = _useLayoutEffect e $ args2 a b
-- | Like useLayoutEffect, but with 3 memo values
useLayoutEffect3 :: forall a b c. a -> b -> c ->
HookEffect
-> Hooks Unit
useLayoutEffect3 :: forall a b c. a -> b -> c ->
Effect (Effect Unit)
-> Hooks Unit
useLayoutEffect3 a b c e = _useLayoutEffect e $ args3 a b c
-- | Like useLayoutEffect, but with 4 memo values
useLayoutEffect4 :: forall a b c d. a -> b -> c -> d ->
HookEffect
-> Hooks Unit
useLayoutEffect4 :: forall a b c d. a -> b -> c -> d ->
Effect (Effect Unit)
-> Hooks Unit
useLayoutEffect4 a b c d e = _useLayoutEffect e $ args4 a b c d
-- | Like useLayoutEffect, but with 5 memo values
useLayoutEffect5 :: forall a b c d e. a -> b -> c -> d -> e ->
HookEffect
-> Hooks Unit
useLayoutEffect5 :: forall a b c d e. a -> b -> c -> d -> e ->
Effect (Effect Unit)
-> Hooks Unit
useLayoutEffect5 a b c d f e = _useLayoutEffect e $ args5 a b c d f
-- | Like useLayoutEffect, but the provided Effect fn does not return a cleanup handler
useLayoutEffect' :: forall a.
(Unit -> Effect a)
-> Hooks Unit
useLayoutEffect' :: forall a.
Effect a
-> Hooks Unit
useLayoutEffect' = useLayoutEffect <<< thenNothing
-- | Like useLayoutEffect1, but the provided Effect fn does not return a cleanup handler
useLayoutEffect1' :: forall a b. a ->
(Unit -> Effect b)
-> Hooks Unit
useLayoutEffect1' :: forall a b. a ->
Effect b
-> Hooks Unit
useLayoutEffect1' a = useLayoutEffect1 a <<< thenNothing
-- | Like useLayoutEffect2, but the provided Effect fn does not return a cleanup handler
useLayoutEffect2' :: forall a b c. a -> b ->
(Unit -> Effect c)
-> Hooks Unit
useLayoutEffect2' :: forall a b c. a -> b ->
Effect c
-> Hooks Unit
useLayoutEffect2' a b = useLayoutEffect2 a b <<< thenNothing
-- | Like useLayoutEffect3, but the provided Effect fn does not return a cleanup handler
useLayoutEffect3' :: forall a b c d. a -> b -> c ->
(Unit -> Effect d)
-> Hooks Unit
useLayoutEffect3' :: forall a b c d. a -> b -> c ->
Effect d
-> Hooks Unit
useLayoutEffect3' a b c = useLayoutEffect3 a b c <<< thenNothing
-- | Like useLayoutEffect4, but the provided Effect fn does not return a cleanup handler
useLayoutEffect4' :: forall a b c d e. a -> b -> c -> d ->
(Unit -> Effect e)
-> Hooks Unit
useLayoutEffect4' :: forall a b c d e. a -> b -> c -> d ->
Effect e
-> Hooks Unit
useLayoutEffect4' a b c d = useLayoutEffect4 a b c d <<< thenNothing
-- | Like useLayoutEffect5, but the provided Effect fn does not return a cleanup handler
useLayoutEffect5' :: forall a b c d e f. a -> b -> c -> d -> e ->
(Unit -> Effect f)
-> Hooks Unit
useLayoutEffect5' :: forall a b c d e f. a -> b -> c -> d -> e ->
Effect f
-> Hooks Unit
useLayoutEffect5' a b c d f = useLayoutEffect5 a b c d f <<< thenNothing
_useLayoutEffect :: forall a.
HookEffect
-> a -> Hooks Unit
_useLayoutEffect :: forall a.
Effect (Effect Unit)
-> a -> Hooks Unit
_useLayoutEffect e a =
hook $ \_ ->
pure $ react ... "useLayoutEffect" $
args2
(wrapEffect e)
(Array.from a)
args2
e
(Array.from a)
-- useMemo
-- | Given a function to compu
r
e an expensive value, returns the value
-- | Given a function to compu
t
e an expensive value, returns the value
useMemo :: forall t. (Unit -> t) -> Hooks t
useMemo f = hook $ \_ -> pure $ react ... "useMemo" $ [ delay unit (\_ -> pure (f unit)) ]
...
...
@@ -251,7 +246,7 @@ _useMemo f a =
-- useCallback
-- | Given a function to compu
r
e an expensive value, returns the value
-- | Given a function to compu
t
e an expensive value, returns the value
useCallback :: forall t. (Unit -> t) -> Hooks (Effect t)
useCallback f = hook $ \_ -> pure $ react ... "useCallback" $ [ delay unit (\_ -> pure (f unit)) ]
...
...
@@ -283,39 +278,35 @@ _useCallback f a =
-- useImperativeHandle
useImperativeHandle
:: forall r r'
. Ref r -> (Unit -> Effect r') -> Hooks Unit
useImperativeHandle :: forall r r'. Ref r -> Effect r' -> Hooks Unit
useImperativeHandle r f =
hook $ \_ ->
pure $ react ... "useImperativeHandle" $ args2 r f
useImperativeHandle1
:: forall a r r'
. a -> Ref r -> (Unit -> Effect r') -> Hooks Unit
useImperativeHandle1 :: forall a r r'. a -> Ref r -> Effect r' -> Hooks Unit
useImperativeHandle1 a r f = _useImperativeHandle r f [a]
useImperativeHandle2
:: forall a b r r'
. a -> b -> Ref r ->
(Unit -> Effect r')
-> Hooks Unit
. a -> b -> Ref r ->
Effect r'
-> Hooks Unit
useImperativeHandle2 a b r f = _useImperativeHandle r f (args2 a b)
useImperativeHandle3
:: forall a b c r r'
. a -> b -> c -> Ref r ->
(Unit -> Effect r')
-> Hooks Unit
. a -> b -> c -> Ref r ->
Effect r'
-> Hooks Unit
useImperativeHandle3 a b c r f = _useImperativeHandle r f (args3 a b c)
useImperativeHandle4
:: forall a b c d r r'
. a -> b -> c -> d -> Ref r ->
(Unit -> Effect r')
-> Hooks Unit
. a -> b -> c -> d -> Ref r ->
Effect r'
-> Hooks Unit
useImperativeHandle4 a b c d r f = _useImperativeHandle r f (args4 a b c d)
useImperativeHandle5
:: forall a b c d e r r'
. a -> b -> c -> d -> e -> Ref r ->
(Unit -> Effect r')
-> Hooks Unit
. a -> b -> c -> d -> e -> Ref r ->
Effect r'
-> Hooks Unit
useImperativeHandle5 a b c d e r f = _useImperativeHandle r f (args5 a b c d e)
_useImperativeHandle :: forall r r' a. Ref r ->
(Unit -> Effect r')
-> a -> Hooks Unit
_useImperativeHandle :: forall r r' a. Ref r ->
Effect r'
-> a -> Hooks Unit
_useImperativeHandle r f a = hook $ \_ ->
pure $ react ... "useImperativeHandle" $
args3 r
(delay unit f)
(Array.from a)
args3 r
f
(Array.from a)
test/Reactix/React/Spec.purs
View file @
8df9707e
...
...
@@ -21,6 +21,7 @@ import DOM.Simple as DOM
import DOM.Simple.Document as Document
import DOM.Simple.Element as Element
import DOM.Simple.Event as Event
import FFI.Simple (delay)
import Reactix as R
import Reactix.Test as RT
import Reactix.DOM.HTML ( button, div, i, text )
...
...
@@ -50,9 +51,9 @@ counterCpt :: R.Component CounterProps
counterCpt = R.hooksComponent "Counter" cpt
where
cpt {count} _ = do
y /\ setY <- R.useState
$ \_ -> pure
count
y /\ setY <- R.useState
'
count
pure $ div { className: "counter" }
[ button { type: "button", onClick: onclick setY (
y
+ 1) } [ text "++" ]
[ button { type: "button", onClick: onclick setY (
_
+ 1) } [ text "++" ]
, div {} [ text (show y) ] ]
onclick set to = mkEffectFn1 $ \e -> set to
...
...
@@ -148,9 +149,9 @@ type EffectorProps = ( stateRef :: Ref.Ref EffectorState )
effectorCpt :: R.Component EffectorProps
effectorCpt = R.hooksComponent "Effector" cpt
where cpt {stateRef} _ = do
R.useEffect $
\_ ->
do
R.useEffect $ do
Ref.write Initialised stateRef
pure $
\_ ->
Ref.write Done stateRef
pure $ Ref.write Done stateRef
pure $ div {} []
-- TODO: test it's firing at the right time
...
...
@@ -176,9 +177,9 @@ effectorTest =
layoutEffectorCpt :: R.Component EffectorProps
layoutEffectorCpt = R.hooksComponent "LayoutEffector" cpt
where cpt {stateRef} _ = do
R.useLayoutEffect $
\_ ->
do
R.useLayoutEffect $ do
Ref.write Initialised stateRef
pure $ \_ -> Ref.write Done stateRef
pure $
delay unit $
\_ -> Ref.write Done stateRef
pure $ div {} []
-- TODO: test it's firing at the right time
...
...
@@ -222,14 +223,14 @@ themeChooserCpt :: R.Component ThemeChooserProps
themeChooserCpt = R.hooksComponent "ThemeChooser" cpt
where
cpt props _ = do
theme /\ setTheme <- R.useState'
$
Nothing
theme /\ setTheme <- R.useState' Nothing
ref <- R.useRef $ R.createContext Nothing
let context = R.readRef ref
pure $
div {}
[ button { type: "button", onClick: onclick setTheme
Nothing
} [ text "None" ]
, button { type: "button", onClick: onclick setTheme (Just Dark) } [ text "Dark" ]
, button { type: "button", onClick: onclick setTheme (Just Light) } [ text "Light" ]
[ button { type: "button", onClick: onclick setTheme
(const Nothing)
} [ text "None" ]
, button { type: "button", onClick: onclick setTheme (
const $
Just Dark) } [ text "Dark" ]
, button { type: "button", onClick: onclick setTheme (
const $
Just Light) } [ text "Light" ]
, R.provideContext context theme [ R.createElement themedCpt { theme: context } [] ] ]
onclick setTheme theme = mkEffectFn1 $ \_ -> setTheme theme
themeChooserTest :: Spec Unit
...
...
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