bucklescript-tea
Version:
TEA for Bucklescript
74 lines (60 loc) • 3.17 kB
Markdown
## ReasonReact Integration Example
This example describes how to integrate the Bucklescript TEA framework into a ReasonReact component. This is useful if you want to migrate an existing ReasonReact project to use Bucklescript TEA, or simply use it for a single component. You'll soon learn to love "The Elm Architecture" way of designing frontend components and their logic.
See issue https://github.com/OvermindDL1/bucklescript-tea/issues/121 for the beginning of this discussion. The resulting code can be seen below.
The process is as follows:
1. Import the Reason/OCaml Bucklescript-TEA component.
2. Get access to the HTML DOM document object, to later be able to get a reference to the React HTML element.
3. Use a ReasonReact `reducerComponent` so that you can more easily store the TEA component state and manage its lifecycle.
4. When the React component mounts, the `didMount` callback is called and the `RenderMain` action is sent.
5. Because there are side-effects in the `RenderMain` action handler, use the `UpdateWithSideEffects` method to change the current state from `Start` to `Initialized`.
6. The Bucklescript-TEA component is mounted on the DIV HTML element using a predefined HTML `id` - in this case `Tea`.
7. The ReasonReact component can now be used in an existing ReasonReact project, and using React props for example the TEA component can be interacted with via the `pushMsg` method to pass actions through to the TEA component, like `Reset` as seen in the example.
```reason
open Tea; /* Reason/OCaml Bucklescript-TEA component, as seen in existing examples */
/*
EXAMPLE CONSOLE LOG (using BuckleScripts Js module)
*/
Js.log("Hello, from BuckleScript and Reason!");
type document; /* abstract type for a document object */
[.send] external getElementById: (document, string) => Js.null_undefined(Web.Node.t) = "getElementById";
[.val] external doc: document = "document";
type action = RenderMain;
type state = Start | Initialized;
// Define interface method types and create mutable references
type pushMsg = (msg) => unit;
let pushMsg: pushMsg = (msg) => ();
let pushMsgRef = ref(pushMsg);
type shutdown = (unit) => unit;
let shutdown: shutdown = () => ();
type getHtmlString = (unit) => string;
let getHtmlString: getHtmlString = () => "";
type interface = (unit) => Tea_app.programInterface(msg);
[.obj]
external makeProgramInterface:
(
~pushMsg: 'msg => unit,
~shutdown: unit => unit,
~getHtmlString: unit => string
) =>
Tea_app.programInterface('msg) =
"";
let interfaceRef = ref(makeProgramInterface(~pushMsg=(msg)=>(), ~shutdown=()=>(), ~getHtmlString=()=>""));
let id = "Tea";
let component = ReasonReact.reducerComponent(id);
let make = (_children) => {
...component,
initialState: _state => Start,
reducer: (_action, _state) =>
switch (_action) {
| RenderMain => UpdateWithSideEffects(Initialized, (_) => {
{
interfaceRef := main(getElementById(doc, id))();
pushMsgRef := (interfaceRef^)##pushMsg;
pushMsgRef^(Reset);
}
})
},
didMount: _self => _self.send(RenderMain),
render: _self => <div id=id />
}
```