Skip to content

Commit

Permalink
Add support for createRef API (#172)
Browse files Browse the repository at this point in the history
* Get refs compiling

* Tidy up

* Actually include Refs files, duh

* Bugfix Ref.js

* Add bower.json file

* HTMLElement -> NativeNode

* Lift callback refs into an object

* Missed reference to HTMLElement

* Remove unneeded import

* Comments

* DOM -> Node
  • Loading branch information
elliotdavies authored and ethul committed Aug 10, 2019
1 parent a2e40f9 commit 4bf5a5a
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 11 deletions.
9 changes: 2 additions & 7 deletions src/React.purs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ module React
, pureComponentWithDerivedState
, statelessComponent
, ReactClass
, ReactRef
, getProps
, getState
, setState
Expand Down Expand Up @@ -68,11 +67,11 @@ module React

import Prelude

import Data.Nullable (Nullable)
import Effect (Effect)
import Effect.Exception (Error)
import Effect.Uncurried (EffectFn1)
import Prim.Row as Row
import React.Ref as Ref
import Type.Row (type (+))
import Unsafe.Coerce (unsafeCoerce)

Expand Down Expand Up @@ -252,10 +251,6 @@ foreign import data ReactClass :: Type -> Type

foreign import fragment :: ReactClass { children :: Children }

-- | Type for React refs. This type is opaque, but you can use `Data.Foreign`
-- | and `DOM` to validate the underlying representation.
foreign import data ReactRef :: Type

-- | Read the component props.
foreign import getProps :: forall props state.
ReactThis props state ->
Expand Down Expand Up @@ -340,7 +335,7 @@ class ReactPropFields (required :: # Type) (given :: # Type)

type ReservedReactPropFields r =
( key :: String
, ref :: SyntheticEventHandler (Nullable ReactRef)
, ref :: Ref.RefHandler Ref.ReactInstance
| r
)

Expand Down
7 changes: 3 additions & 4 deletions src/React/DOM/Props.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ module React.DOM.Props where

import Prelude

import Data.Nullable (Nullable)
import Effect (Effect)
import Effect.Uncurried (mkEffectFn1)
import React (ReactRef)
import React.Ref as Ref
import React.SyntheticEvent
( SyntheticEvent
, SyntheticAnimationEvent
Expand Down Expand Up @@ -894,8 +893,8 @@ onScrollCapture f = unsafeMkProps "onScrollCapture" (mkEffectFn1 f)
onWheelCapture :: (SyntheticWheelEvent -> Effect Unit) -> Props
onWheelCapture f = unsafeMkProps "onWheelCapture" (mkEffectFn1 f)

ref :: (Nullable ReactRef -> Effect Unit) -> Props
ref f = unsafeMkProps "ref" (mkEffectFn1 f)
ref :: Ref.RefHandler Ref.NativeNode -> Props
ref = unsafeMkProps "ref"

suppressContentEditableWarning :: Boolean -> Props
suppressContentEditableWarning = unsafeMkProps "suppressContentEditableWarning"
Expand Down
13 changes: 13 additions & 0 deletions src/React/Ref.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
"use strict";

var React = require("react");

exports.createRef = React.createRef;

exports.liftCallbackRef = function(ref) {
return { current: ref };
}

exports.getCurrentRef_ = function(ref) {
return ref.current;
}
57 changes: 57 additions & 0 deletions src/React/Ref.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module React.Ref
( Ref
, RefHandler
, ReactInstance
, NativeNode
, fromRef
, fromEffect
, getCurrentRef
, createNodeRef
, createInstanceRef
) where

import Prelude
import Effect (Effect)
import Data.Maybe (Maybe)
import Data.Nullable (Nullable)
import Data.Nullable as Nullable
import Effect.Uncurried (EffectFn1, runEffectFn1, mkEffectFn1)
import Unsafe.Coerce (unsafeCoerce)

--- | An instance of a React class.
foreign import data ReactInstance :: Type

--- | A platform-specific native layout node. On the web this will be a DOM
--- | element (see `Web.HTML.HTMLElement`).
foreign import data NativeNode :: Type

foreign import data Ref :: Type -> Type

foreign import data RefHandler :: Type -> Type


foreign import createRef :: forall a. Effect (Ref a)

foreign import liftCallbackRef :: forall a. Ref a -> Ref a


createNodeRef :: Effect (Ref NativeNode)
createNodeRef = createRef


createInstanceRef :: Effect (Ref ReactInstance)
createInstanceRef = createRef


fromRef :: forall a. Ref a -> RefHandler a
fromRef = unsafeCoerce


fromEffect :: forall a. (Ref a -> Effect Unit) -> RefHandler a
fromEffect f = unsafeCoerce $ mkEffectFn1 (f <<< liftCallbackRef)


foreign import getCurrentRef_ :: forall a. EffectFn1 (Ref a) (Nullable a)

getCurrentRef :: forall a. Ref a -> Effect (Maybe a)
getCurrentRef ref = Nullable.toMaybe <$> runEffectFn1 getCurrentRef_ ref

0 comments on commit 4bf5a5a

Please sign in to comment.