react-haskell-2.0.1: Haskell React bindings

Copyright(C) 2014-15 Joel Burget
MaintainerJoel Burget <>
Safe HaskellNone





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 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 (see classTransition)
  • exsig: The type of signals this class emits (see classTransition)
  • ctx: This is only used for React's mythical context feature -- If you know what that is, see childContext for usage.

data ClassConfig props state insig exsig ctx Source




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) Source

A type that can be used in a child context.

React manages context (unlike props and state, which are managed entirely within Haskell), so anything used in child context must be convertable to a JSRef and must be describable by a PropType.

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.


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


data EventProperties e Source

Low level properties common to all events


Native Events

Synthetic Events


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


newtype NoProps Source

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.


pageLayout_ :: ReactNode () -> ReactNode () pageLayout_ = importParentClass pageLayout noProps


NoProps () 

noProps :: NoProps Source

Used when importing a foreign class taking no props. See above example.

mkStaticAttr :: ToJSON a => Text -> a -> 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


type ExportedClass = JSRef ExportedClass_ Source

JS Interop

type ImportedClass props sig = JSRef (ImportedClass_ props sig) Source


class PropTypable a Source

Describe the PropType of a type


propType (_ :: JSString) = PropString IsRequired

propType (_ :: Bool) = PropBool IsRequired

Minimal complete definition