Copyright | (C) 2014-15 Joel Burget |
---|---|
License | MIT |
Maintainer | Joel Burget <joelburget@gmail.com> |
Stability | experimental |
Portability | non-portable |
Safe Haskell | None |
Language | Haskell2010 |
Usage:
This tutorial assumes only a basic understanding of React, the DOM, and browser events. I recomment at least skimming the official React tutorial.
Let's start with a basic example:
page_ :: ReactNode Void page_ = let cls = smartClass { name = "page" -- initially the input is empty , initialState = "" -- always transition to the input's new value , transition = (_, value) -> (value, Nothing) , renderFn = _ str -> div_ [ class_ "container" ] $ do input_ [ value_ str, onChange (Just . value . target) ] } in classLeaf cls () main :: IO () main = do Just doc <- currentDocument Just elem <- documentGetElementById doc ("elem" :: JSString) render page_ elem
In this example we defined a React class with Text
state, but taking only
()
as a prop. It's possible to use anything for props and state --
numbers, JSON, even React classes.
In the example the input always contains the state from the class, and the state is updated on every input change event -- effectively, every keystroke.
- data ReactClass props state insig exsig ctx
- data ClassConfig props state insig exsig ctx = ClassConfig {
- renderFn :: props -> state -> ReactNode insig
- initialState :: state
- name :: JSString
- transition :: (state, insig) -> (state, Maybe exsig)
- startupSignals :: [insig]
- childContext :: Maybe (HashMap Text ctx)
- type ClassCtx a = (ToJSRef a, PropTypable a)
- smartClass :: ClassConfig props state insig exsig JSString
- dumbClass :: ClassConfig props () sig sig JSString
- render :: ReactNode Void -> Element -> IO ()
- debugRender :: Show sig => ReactNode sig -> Element -> IO ()
- data ReactNode sig
- data EventProperties e = EventProperties {
- bubbles :: !Bool
- cancelable :: !Bool
- currentTarget :: !e
- defaultPrevented :: !Bool
- eventPhase :: !Int
- isTrusted :: !Bool
- evtTarget :: !e
- eventType :: !JSString
- data Target = Target {}
- data ModifierKeys = ModifierKeys {}
- data MouseEvent = MouseEvent {}
- data KeyboardEvent = KeyboardEvent {}
- data ChangeEvent = ChangeEvent {}
- data FocusEvent = FocusEvent
- data BlurEvent = BlurEvent
- onBlur :: (BlurEvent -> Maybe s) -> AttrOrHandler s
- onFocus :: (FocusEvent -> Maybe s) -> AttrOrHandler s
- onChange :: (ChangeEvent -> Maybe s) -> AttrOrHandler s
- onKeyDown :: (KeyboardEvent -> Maybe s) -> AttrOrHandler s
- onKeyPress :: (KeyboardEvent -> Maybe s) -> AttrOrHandler s
- onKeyUp :: (KeyboardEvent -> Maybe s) -> AttrOrHandler s
- onMouseEnter :: (MouseEvent -> Maybe s) -> AttrOrHandler s
- onMouseLeave :: (MouseEvent -> Maybe s) -> AttrOrHandler s
- onDoubleClick :: (MouseEvent -> Maybe s) -> AttrOrHandler s
- onClick :: (MouseEvent -> Maybe s) -> AttrOrHandler s
- onEnter :: s -> AttrOrHandler s
- class GeneralizeSignal sigloc siggen where
- generalizeSignal :: sigloc -> siggen
- locally :: GeneralizeSignal sigloc siggen => ReactNode sigloc -> ReactNode siggen
- data AttrOrHandler signal
- newtype NoProps = NoProps ()
- noProps :: NoProps
- mkStaticAttr :: ToJSON a => Text -> a -> AttrOrHandler sig
- key_ :: Text -> AttrOrHandler sig
- class_ :: Text -> AttrOrHandler sig
- href_ :: Text -> AttrOrHandler sig
- id_ :: Text -> AttrOrHandler sig
- src_ :: Text -> AttrOrHandler sig
- value_ :: Text -> AttrOrHandler sig
- placeholder_ :: Text -> AttrOrHandler sig
- for_ :: Text -> AttrOrHandler sig
- type_ :: Text -> AttrOrHandler sig
- checked_ :: Bool -> AttrOrHandler sig
- autofocus_ :: Bool -> AttrOrHandler sig
- width_ :: Double -> AttrOrHandler sig
- height_ :: Double -> AttrOrHandler sig
- cx_ :: Double -> AttrOrHandler sig
- cy_ :: Double -> AttrOrHandler sig
- d_ :: Double -> AttrOrHandler sig
- dx_ :: Double -> AttrOrHandler sig
- dy_ :: Double -> AttrOrHandler sig
- x_ :: Double -> AttrOrHandler sig
- y_ :: Double -> AttrOrHandler sig
- r_ :: Double -> AttrOrHandler sig
- fill_ :: Text -> AttrOrHandler sig
- viewBox_ :: Text -> AttrOrHandler sig
- points_ :: Text -> AttrOrHandler sig
- transform_ :: Text -> AttrOrHandler sig
- classParent :: ClassCtx ctx => ClassConfig props state insig exsig ctx -> ReactNode insig -> props -> ReactNode exsig
- classLeaf :: ClassCtx ctx => ClassConfig props state insig exsig ctx -> props -> ReactNode exsig
- exportClassLeaf :: ClassCtx ctx => ClassConfig props state insig exsig ctx -> ExportedClass
- importLeafClass :: ToJSRef props => ImportedClass props sig -> props -> ReactNode sig
- importParentClass :: ToJSRef props => ImportedClass props sig -> props -> ReactNode sig -> ReactNode sig
- data ExportedNode sig
- type ExportedClass = JSRef ExportedClass_
- type ImportedClass props sig = JSRef (ImportedClass_ props sig)
- data PropRequired
- data PropType
- class PropTypable a
Classes
data ReactClass props state insig exsig ctx Source
A ReactClass
is a standalone component of a user interface which
contains the state necessary to render itself. Classes are a tool for
scoping.
Use createClass
to construct.
props
: The type of props passed in.state
: The type of state this class maintains.insig
: The type of signals this class handles (seeclassTransition
)exsig
: The type of signals this class emits (seeclassTransition
)ctx
: This is only used for React's mythical context feature -- If you know what that is, seechildContext
for usage.
data ClassConfig props state insig exsig ctx Source
ClassConfig | |
|
type ClassCtx a = (ToJSRef a, PropTypable a) Source
smartClass :: ClassConfig props state insig exsig JSString Source
Defaults for a stateful ("controller") class.
dumbClass :: ClassConfig props () sig sig JSString Source
Defaults for a stateless ("layout") class.
Rendering
render :: ReactNode Void -> Element -> IO () Source
Render a top-level component.
Note that the rendered component can't possibly emit signals.
debugRender :: Show sig => ReactNode sig -> Element -> IO () Source
Unlike render
, debugRender
can render components that emit signals, as
long as they can be shown.
React Nodes
Events
data EventProperties e Source
Low level properties common to all events
EventProperties | |
|
NFData e => NFData (EventProperties e) Source |
data ModifierKeys Source
data FocusEvent Source
Native Events
onBlur :: (BlurEvent -> Maybe s) -> AttrOrHandler s Source
onFocus :: (FocusEvent -> Maybe s) -> AttrOrHandler s Source
onChange :: (ChangeEvent -> Maybe s) -> AttrOrHandler s Source
onKeyDown :: (KeyboardEvent -> Maybe s) -> AttrOrHandler s Source
onKeyPress :: (KeyboardEvent -> Maybe s) -> AttrOrHandler s Source
onKeyUp :: (KeyboardEvent -> Maybe s) -> AttrOrHandler s Source
onMouseEnter :: (MouseEvent -> Maybe s) -> AttrOrHandler s Source
onMouseLeave :: (MouseEvent -> Maybe s) -> AttrOrHandler s Source
onDoubleClick :: (MouseEvent -> Maybe s) -> AttrOrHandler s Source
onClick :: (MouseEvent -> Maybe s) -> AttrOrHandler s Source
Synthetic Events
onEnter :: s -> AttrOrHandler s Source
Local
class GeneralizeSignal sigloc siggen where Source
Implement when a local signal can be generalized to a higher level one. Used
by locally
generalizeSignal :: sigloc -> siggen Source
locally :: GeneralizeSignal sigloc siggen => ReactNode sigloc -> ReactNode siggen Source
locally
exists to make it simple to embed classes with local concerns. An
example will be helpful:
We have some page which can respond to many different events.
data Transition = UserTyping JSString | Toggle ... globalPage_ :: [AttrOrHandler Transition] -> ReactNode Transition
And we want to be able to embed some components that don't care about all
that. inputBox_
can only output JSString
and pageHeader_
can't send
any signals at all.
inputBox_ :: ReactNode JSString pageHeader_ :: ReactNode Void
With locally we can easily embed them in globalPage_
:
instance GeneralizeSignal JSString Transition where generalizeSignal = UserTyping -- (globalPage_) renderFn = props state -> div_ [ class_ "global-page" ] $ do locally pageHeader_ ... locally inputBox_ ...
data AttrOrHandler signal Source
Attributes
When importing a foreign class you must specify the props it takes. In the
common case where it takes no props, only handles layout, it's convenient to
specify the type of props as NoProps
.
Example:
pageLayout_ :: ReactNode () -> ReactNode () pageLayout_ = importParentClass pageLayout noProps
NoProps () |
mkStaticAttr :: ToJSON a => Text -> a -> AttrOrHandler sig Source
key_ :: Text -> AttrOrHandler sig Source
class_ :: Text -> AttrOrHandler sig Source
href_ :: Text -> AttrOrHandler sig Source
id_ :: Text -> AttrOrHandler sig Source
src_ :: Text -> AttrOrHandler sig Source
value_ :: Text -> AttrOrHandler sig Source
placeholder_ :: Text -> AttrOrHandler sig Source
for_ :: Text -> AttrOrHandler sig Source
type_ :: Text -> AttrOrHandler sig Source
checked_ :: Bool -> AttrOrHandler sig Source
autofocus_ :: Bool -> AttrOrHandler sig Source
width_ :: Double -> AttrOrHandler sig Source
height_ :: Double -> AttrOrHandler sig Source
cx_ :: Double -> AttrOrHandler sig Source
cy_ :: Double -> AttrOrHandler sig Source
d_ :: Double -> AttrOrHandler sig Source
dx_ :: Double -> AttrOrHandler sig Source
dy_ :: Double -> AttrOrHandler sig Source
x_ :: Double -> AttrOrHandler sig Source
y_ :: Double -> AttrOrHandler sig Source
r_ :: Double -> AttrOrHandler sig Source
fill_ :: Text -> AttrOrHandler sig Source
viewBox_ :: Text -> AttrOrHandler sig Source
points_ :: Text -> AttrOrHandler sig Source
transform_ :: Text -> AttrOrHandler sig Source
Creating Elements
Class creation
classParent :: ClassCtx ctx => ClassConfig props state insig exsig ctx -> ReactNode insig -> props -> ReactNode exsig Source
classLeaf :: ClassCtx ctx => ClassConfig props state insig exsig ctx -> props -> ReactNode exsig Source
JS Interop
exportClassLeaf :: ClassCtx ctx => ClassConfig props state insig exsig ctx -> ExportedClass Source
importLeafClass :: ToJSRef props => ImportedClass props sig -> props -> ReactNode sig Source
importParentClass :: ToJSRef props => ImportedClass props sig -> props -> ReactNode sig -> ReactNode sig Source
data ExportedNode sig Source
ToJSRef (ExportedNode sig) Source |
type ExportedClass = JSRef ExportedClass_ Source
JS Interop
type ImportedClass props sig = JSRef (ImportedClass_ props sig) Source
PropTypes
The equivalent to React propTypes.
class PropTypable a Source
Describe the PropType of a type
Examples:
propType (_ :: JSString) = PropString IsRequired propType (_ :: Bool) = PropBool IsRequired
propType