bouzuya.hatenablog.com

ぼうずやのにっき

purescript-react-basic の element を使う

2018-12-13 に purescript-react-basic で dangerouslySetInnerHTML という記事を書いたのだけどもっと良い別の方法もあるようだ。 purescript-react-basic には element という関数で React コンポーネントを使うことができる。要するに dangerouslySetInnerHTML を使う React コンポーネントを用意し foreign import して element でそれを使ってしまうという方法だ。

さっそく見ていく。 React.Basic モジュールから element および ReactComponent を使う。

element :: forall props. ReactComponent { | props } -> { | props } -> JSX

Create a JSX node from a ReactComponent, by providing the props.

This function is for non-React-Basic React components, such as those imported from FFI.

data ReactComponent props

Represents a traditional React component. Useful for JavaScript interop and FFI. For example:

foreign import ComponentRequiringJSHacks :: ReactComponent { someProp :: String }

どちらもきちんとドキュメントに書いてある。

これで前回の bbn-viewer のものを置き換えてみる。

foreign import unsafeHtmlComponent :: forall props. ReactComponent { html :: String | props }
-- ...
render :: Self Props State Action -> JSX
render self =
-- ...
        , element unsafeHtmlComponent { html: Markdown.toHtmlString self.state.article }
-- ...
"use strict";

var React = require('react');
var createReactClass = require('create-react-class');

exports.unsafeHtmlComponent = createReactClass({
  render: function () {
    return React.createElement(
      'div', { dangerouslySetInnerHTML: { __html: this.props.html } }
    );
  }
});

動いた。簡単だ。 PureScript の制限により *.jsJSXclass などが使えない点は注意してほしい。

前回のもの今回のものを比べればその簡単さが分かる。

これは別に dangerouslySetInnerHTML に限らずとても便利だ。これができるなら purescript-react-basic でなんとでもできそうだ。良い。