React Nativeアプリ開発でinnerHTML風な対応が要求された。APIの返り値にHTMLタグが含まれているデータをレンダリングするというものだ。
賢明なあなたにおかれては、<WebView/>
を使えばいいじゃん!と思ったに違いない。
そう。そのとおりでWebViewによってHTMLタグを含んだ値をレンダリングすることが可能だ。しかし何かしらのイベントでHTMLタグに付与された属性値を参照する、という処理に悩まされてしまった次第である。
ひとしきりgithubやjs.coachを回遊して見つけたのが「react-native-render-html」だ。
このエントリーでは、HTMLデータを解釈して適当なネイティブビューにレンダリングする「react-native-render-html」を紹介したい。
react-native-render-htmlについて
react-native-render-htmlは、HTMLタグを含む文字列値をWebViewを介さず100%ネイティブビューにレンダリングするReact Nativeコンポーネントだ。ネイティブビュー要素は、それぞれ適当なスタイルが当てられる。Normalize.cssが適用されているような状態を思い出してもらうと相違が少ないはずだ。
【react-native-render-html】
https://github.com/archriss/react-native-render-html#creating-custom-renderers
特徴
- WebViewじゃない
- HTMLを100%ネイティブビューにする
- ネイティブビュー要素はあらかじめスタイルが適用されている
- スタイルをカスタマイズできる
- HTMLタグ個別にカスタマイズできる
導入
$ npm install react-native-render-html --save
# or
$ yarn add react-native-render-html
Expo環境下で開発をしているならば、つぎのコマンドでもよいだろう。expo install
ならばバージョンが整合しているものをインストールしてくれる。
$ expo install react-native-render-html
デモンストレーション
それではもっともシンプルな実装例をご覧いただこう。
import React from 'react';
import { StyleSheet, ScrollView } from 'react-native';
import HTML from 'react-native-render-html'; // ?
const htmlContent = `
<h1>This HTML snippet is now rendered with native components !</h1>
<h2>Enjoy a webview-free and blazing fast application</h2>
<img src="https://i.imgur.com/dHLmxfO.jpg?2" />
<em style="textAlign: center;">Look at how happy this native cat is</em>
`;
export default function App() {
return (
<ScrollView style={styles.container}>
<HTML html={ htmlContent } /> // ?
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
ファイル冒頭でreact-native-render-htmlのHTMLコンポーネントをインポートしている。そののhtml propsにhtmlContent定数を与えている。定数にはHTMLタグで構成された文字列値が格納されている。これがレンダリングされた状態が下図である。先に述べたとおりNormalize.css適用時の装いをしているのがわかると思う。
HTML属性値を取得する
先ほどのシンプルな例では、Normalize.css適用時の装いをしていたけれども、それだけという要件は少ないだろうと思う。きっと特定タグになにかしらのイベント処理を施す必要に迫られる。以下の実装例は、<span/>
に固有のスタイル適用とonPressイベントハンドラを定義している。
import React from 'react';
import { StyleSheet, View, Text } from 'react-native';
import HTML from 'react-native-render-html'; // ?
const htmlContent = `この<span data-yomi="ぶんしょう">文章</span>はダミーです。文字の大きさ、量、字間、行間等を<span data-yomi="かくにん">確認</span>するために入れています。`;
export default function App() {
return (
<View style={ styles.container }>
<HTML
html={ htmlContent }
baseFontStyle={{
fontSize: 14,
lineHeight: 22,
textAlign: 'justify',
}}
renderers={{
span: (htmlAttribs, children, convertedCSSStyles, passProps) => ( // ?
<Text
key={ passProps.key }
style={ styles.span }
onPress={() => {
console.log(htmlAttribs['data-yomi']);
}}
>
{ children }
</Text>
),
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
span: {
color: '#f00',
fontWeight: 'bold',
}
});
まとめ
HTMLデータを解釈して適当なネイティブビューにレンダリングする「react-native-render-html」React Nativeコンポーネントの紹介だった。
実際に案件で使ってみて、innerHTML風に扱うことができる印象を受けた。HTML属性値を取得する項目でやったような実装をWebViewでやっていたら、きっと相当に悩まされていたに違いない。とても有用なReact Nativeコンポーネントではないだろうか。
このエントリーが、あなたのクリエイティビティを刺激するものであると期待したい。