-
Notifications
You must be signed in to change notification settings - Fork 65
Initial hooks implementation #159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
90e61f0
0e5d81b
1088218
53d8011
102d044
a60a253
e29447e
e39a96c
140c3bc
4e456da
2c1a2cc
088d175
7b5ec57
e8b5738
edcd569
ba17b83
ebe5f47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,19 +16,8 @@ module React.Hook | |
, useCallback | ||
, useMemo | ||
, useRef | ||
, getRef | ||
, setRef | ||
, refToReactRef | ||
, Ref | ||
, useImperativeMethods | ||
, imperativeMethodsInput | ||
, ImperativeMethodsInput | ||
, useMutationEffect | ||
, mutationEffectInput | ||
, MutationEffectInput | ||
, useLayoutEffect | ||
, layoutEffectInput | ||
, LayoutEffectInput | ||
) where | ||
|
||
import Prelude | ||
|
@@ -40,12 +29,12 @@ import Data.Nullable as Nullable | |
import Data.Tuple (Tuple(..)) | ||
|
||
import Effect (Effect) | ||
import Effect.Uncurried (EffectFn1, EffectFn2, runEffectFn1, runEffectFn2) | ||
import Effect.Uncurried (EffectFn1, runEffectFn1) | ||
|
||
import Unsafe.Coerce (unsafeCoerce) | ||
|
||
import React.Context (Context) | ||
import React.Types (ReactRef) | ||
import React.Ref (Ref) | ||
|
||
useState | ||
:: forall a | ||
|
@@ -179,87 +168,37 @@ foreign import useMemo_ | |
useRef :: forall a. Maybe a -> Hook (Ref a) | ||
useRef = runFn1 useRef_ <<< Nullable.toNullable | ||
|
||
refToReactRef :: forall a. Ref a -> ReactRef | ||
refToReactRef = unsafeCoerce | ||
|
||
getRef :: forall a. Ref a -> Effect (Maybe a) | ||
getRef r = Nullable.toMaybe <$> runEffectFn1 getRef_ r | ||
|
||
setRef :: forall a. Ref a -> Maybe a -> Effect Unit | ||
setRef r = runEffectFn2 setRef_ r <<< Nullable.toNullable | ||
|
||
foreign import data Ref :: Type -> Type | ||
|
||
foreign import useRef_ | ||
:: forall a | ||
. Fn1 (Nullable a) | ||
(Hook (Ref a)) | ||
|
||
foreign import getRef_ | ||
:: forall a | ||
. EffectFn1 (Ref a) | ||
(Nullable a) | ||
|
||
foreign import setRef_ | ||
:: forall a | ||
. EffectFn2 (Ref a) | ||
(Nullable a) | ||
Unit | ||
|
||
useImperativeMethods | ||
:: forall r a | ||
:: forall a | ||
. Ref a | ||
-> (Unit -> { | r }) | ||
-> Maybe (Array ImperativeMethodsInput) | ||
-> (Unit -> a) | ||
-> Maybe (Array HookInput) | ||
-> Hook Unit | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about this type. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed that this may not be the best representation. I still need to work this one out a bit more. I am open to suggestions on this. |
||
useImperativeMethods a k = runFn3 useImperativeMethods_ a k <<< Nullable.toNullable | ||
|
||
imperativeMethodsInput :: forall a. a -> ImperativeMethodsInput | ||
imperativeMethodsInput = unsafeCoerce | ||
|
||
foreign import data ImperativeMethodsInput :: Type | ||
|
||
foreign import useImperativeMethods_ | ||
:: forall r a | ||
. Fn3 (Ref a) | ||
(Unit -> { | r }) | ||
(Nullable (Array ImperativeMethodsInput)) | ||
(Hook Unit) | ||
|
||
useMutationEffect | ||
:: forall a | ||
. Effect (Effect a) | ||
-> Maybe (Array MutationEffectInput) | ||
-> Hook Unit | ||
useMutationEffect k = runFn2 useMutationEffect_ k <<< Nullable.toNullable | ||
|
||
mutationEffectInput :: forall a. a -> MutationEffectInput | ||
mutationEffectInput = unsafeCoerce | ||
|
||
foreign import data MutationEffectInput :: Type | ||
|
||
foreign import useMutationEffect_ | ||
:: forall a | ||
. Fn2 (Effect (Effect a)) | ||
(Nullable (Array MutationEffectInput)) | ||
. Fn3 (Ref a) | ||
(Unit -> a) | ||
(Nullable (Array HookInput)) | ||
(Hook Unit) | ||
|
||
useLayoutEffect | ||
:: forall a | ||
. Effect (Effect a) | ||
-> Maybe (Array LayoutEffectInput) | ||
-> Maybe (Array HookInput) | ||
-> Hook Unit | ||
useLayoutEffect k = runFn2 useLayoutEffect_ k <<< Nullable.toNullable | ||
|
||
layoutEffectInput :: forall a. a -> LayoutEffectInput | ||
layoutEffectInput = unsafeCoerce | ||
|
||
foreign import data LayoutEffectInput :: Type | ||
|
||
foreign import useLayoutEffect_ | ||
:: forall a | ||
. Fn2 (Effect (Effect a)) | ||
(Nullable (Array LayoutEffectInput)) | ||
(Nullable (Array HookInput)) | ||
(Hook Unit) | ||
|
||
foreign import data Hook :: Type -> Type | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
'use strict'; | ||
|
||
var React = require('react'); | ||
|
||
exports.createRef = function createRef() { | ||
return React.createRef(); | ||
}; | ||
|
||
exports.forwardRef_ = function forwardRef(render) { | ||
return React.forwardRef(render); | ||
} | ||
|
||
exports.getRef_ = function getRef_(ref) { | ||
return ref.current; | ||
} | ||
|
||
exports.setRef_ = function setRef_(ref, value) { | ||
ref.current = value; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
module React.Ref | ||
( Ref | ||
, DOMRef | ||
, createRef | ||
, forwardRef | ||
, getRef | ||
, setRef | ||
) where | ||
|
||
import Prelude | ||
|
||
import Data.Function.Uncurried (Fn2, mkFn2) | ||
import Data.Maybe (Maybe) | ||
import Data.Nullable (Nullable) | ||
import Data.Nullable as Nullable | ||
|
||
import Effect (Effect) | ||
import Effect.Uncurried (EffectFn1, EffectFn2, runEffectFn1, runEffectFn2) | ||
|
||
import React.Types (ReactClass, ReactElement) | ||
|
||
-- | Type for React refs. | ||
foreign import data Ref :: Type -> Type | ||
|
||
-- | Type for a Ref value that is a React component instance or a DOM element. | ||
-- | This type is opaque, but you can use `Data.Foreign` and `DOM` to validate the underlying representation. | ||
foreign import data DOMRef :: Type | ||
|
||
foreign import createRef :: forall a. Effect (Ref a) | ||
|
||
forwardRef :: forall props a. (props -> Ref a -> ReactElement) -> ReactClass props | ||
forwardRef = forwardRef_ <<< mkFn2 | ||
|
||
foreign import forwardRef_ | ||
:: forall props a | ||
. Fn2 props (Ref a) ReactElement | ||
-> ReactClass props | ||
|
||
getRef :: forall a. Ref a -> Effect (Maybe a) | ||
getRef r = Nullable.toMaybe <$> runEffectFn1 getRef_ r | ||
|
||
foreign import getRef_ | ||
:: forall a | ||
. EffectFn1 (Ref a) | ||
(Nullable a) | ||
|
||
setRef :: forall a. Ref a -> Maybe a -> Effect Unit | ||
setRef r = runEffectFn2 setRef_ r <<< Nullable.toNullable | ||
|
||
foreign import setRef_ | ||
:: forall a | ||
. EffectFn2 (Ref a) | ||
(Nullable a) | ||
Unit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is correct. A class component isn't going to have a
DOMRef
since it will be pointing to the instance. As is, the only thing that would make sense to me isForeign
. Since we are redoing refs anyway, maybe there's a better way to handle this side of the interface in a typed way... I'm not sure though.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. It could be the instance. I wouldn't mind
Foreign
, but what if we made an opaque typeForwardRef
instead? I am not sure if there is a better way to hand this, but I am open to ideas.