Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle global DOM events in ReasonML/ReasonReact?

What's the most idiomatic way of listening/handling global DOM events in ReasonML.

I'm building a ReasonReact version of the 2048 game where I need to listen for keyboard events.

In a standard JS/React app I'd have a component with a componentDidMount lifecycle method where I would listen to the event with document.addEventListener("keypress", [my_event_handler]) and unlisten to the same on componentWillUnmount with document.removeEventListener("keypress", [my_event_handler]).

What's the most idiomatic way of accessing document.(addEventListener/removeEventListener) in Reason/ReasonReact?

like image 901
Alan R. Soares Avatar asked Jun 27 '18 22:06

Alan R. Soares


2 Answers

You can do pretty much the same thing in ReasonReact–it supports the didMount and willUnmount lifecycle methods, which correspond to their ReactJS namesakes: https://reasonml.github.io/reason-react/docs/en/lifecycles.html

To add and remove event listeners, you can use @glennsl's excellent bs-webapi package: https://redex.github.io/package/bs-webapi

Here are some examples of adding and removing event listeners: https://github.com/reasonml-community/bs-webapi-incubator/blob/24cee2500b9c98355a14896fa9fc4ceb8a3e2258/tests/dom/events/eventTarget_test.re

Putting it all together, you could have a component like this:

/* src/components/MyComponent.re */
let document = Webapi.Dom.Document.asEventTarget(Webapi.Dom.document);
let handleKey = _ => Js.log("Key pressed");
let component = ReasonReact.statelessComponent("MyComponent");
let make = _children => {
  ...component,
  didMount: _self =>
    Webapi.Dom.EventTarget.addEventListener("keypress", handleKey, document),
  willUnmount: _self =>
    Webapi.Dom.EventTarget.removeEventListener("keypress", handleKey, document),
  render: _self => <p> (ReasonReact.string("Hello")) </p>,
};
like image 68
Yawar Avatar answered Dec 06 '22 19:12

Yawar


I ended up writing my own bindings to addEventListener and removeEventListener:

[@bs.val]
external add_keyboard_event_listener :
  (string, ReactEventRe.Keyboard.t => unit) => unit =
  "addEventListener";

[@bs.val]
external remove_keyboard_event_listener :
  (string, ReactEventRe.Keyboard.t => unit) => unit =
  "removeEventListener";
like image 38
Alan R. Soares Avatar answered Dec 06 '22 19:12

Alan R. Soares