Gutenbergブロックの edit
関数や save
関数は返り値として React要素を返すため、その部分をJSXで記述することが可能です。JSXを導入することにより記述が容易になり、可読性の向上も見込めます。
// JSXなし return wp.element.createElement( "h1", { className: "heading" }, "Hello, World" );
// JSXあり return ( <h1 className="heading"> Hello, World </h1> );
今回はGutenberg用備考ブロックを作るで作成したブロックの一部をJSXで書き直したいと思います。最終的なコードはGitLabで公開しているので興味があればご覧ください。
環境のインストール
JSXを使用できるようするにはまず作業環境を整える必要があります。トランスパイルに Babel を使用するため、Node.js をインストールしていない方はまずそちらをインストールします。こちらやこちらの記事などを参考にして npm
コマンドを使用できるようにしましょう。
npm
コマンドが使えるようになったらBabelとJSX用プラグインをインストールします。必要なパッケージは @babel/core
、@babel/cli
、@babel/plugin-transform-react-jsx
です。前回作成したプラグインディレクトリ my-note-plugin
に移動し、以下のコマンドを実行しましょう。
$ npm install -D @babel/core @babel/cli @babel/plugin-transform-react-jsx
インストールが終わると以下のようなディレクトリ構成になっているはずです。
my-note-plugin/ |- node_modules/ |- note-block/ |- my-note-plugin.php `- package-lock.json
これでインストール作業は終わりです。
Babelの設定と実行
Babelの設定は .babelrc
に記述します。
{ "plugins": [ [ "@babel/plugin-transform-react-jsx", { "pragma": "el" } ] ] }
5行目の pragma
にはReact要素を作成する関数名を指定します。例えばReactの場合は React.createElement
、Gutenbergの場合は wp.element.createElement
です。
ただ今回のプラグインでは var el = wp.element.createElement
で関数名を省略しているため、el
を指定しています。もちろんwp.element.createElement
でも大丈夫です。
今回はトランスパイル元ファイルを my-note-plugin/note-block/src/index.js
、トランスパイル先ファイルを my-note-plugin/note-block/index.js
にします。そのため現在の index.js
を my-note-plugin/note-block/src
に移動します。
$ mkdir note-block/src $ mv note-block/index.js src
ここで一度トランスパイルしてみましょう。トランスパイルは以下のコマンドで行います。
$ npx babel note-block/src --out-dir note-block
Babelが正常にインストールされていれば note-block
ディレクトリに index.js
が生成されているはずです。
JSXに書き換え
では edit
関数と save
関数の戻り値をJSXで書き換えましょう。現在のコードでは edit
関数には createEditElement
関数、 save
関数には createSaveElement
関数がそれぞれ指定されているためそちらを変更します。
これを
function createEditElement( props ) { return el( 'div', { className: name }, [ el( wp.editor.RichText, { tagName: 'p', className: name + '__heading', value: props.attributes.heading, onChange: function( heading ) { props.setAttributes( { heading: heading } ); } } ), el( wp.editor.RichText, { tagName: 'div', className: name + '__content', value: props.attributes.content, multiline: 'p', onChange: function( content ) { props.setAttributes( { content: content } ); } } ) ] ); }
こう。11行目から23行目がJSXです。
function createEditElement( props ) { var onChangeHeading = function( heading ) { props.setAttributes( { heading: heading } ); } var onChangeContent = function( content ) { props.setAttributes( { content: content } ); } return ( <div className={name}> <wp.editor.RichText tagName="p" className={name + '__heading'} value={props.attributes.heading} onChange={onChangeHeading} /> <wp.editor.RichText tagName="div" className={name + '__content'} value={props.attributes.content} multiline="p" onChange={onChangeContent} /> </div> ); }
同じように createSaveElement
も
function createSaveElement( props ) { return el( 'div', { }, [ el( wp.editor.RichText.Content, { tagName: 'p', className: name + '__heading', value: props.attributes.heading } ), el( wp.editor.RichText.Content, { tagName: 'div', className: name + '__content', value: props.attributes.content } ) ] ); }
書き換えます。
function createSaveElement( props ) { return ( <div> <wp.editor.RichText.Content tagName="p" className={name + '__heading'} value={props.attributes.heading} /> <wp.editor.RichText.Content tagName="div" className={name + '__content'} value={props.attributes.content} /> </div> ); }
今回のケースではあまりメリットがないように見えますが、要素が入れ子になればなるほどJSXの恩恵を受けることができます。
最後にもう一度トランスパイルをして終了です。
$ npx babel note-block/src --out-dir note-block
おわり
npm
を用意して、 Babel
をインストールして、と環境構築がやや面倒ですが一度用意さえしてしまえばあとはコマンド一つでトランスパイルできるようになります。
関数で記述する方法は敷居は低いですがパッと見どうなっているかがわからず、一つ一つ見ていかないといけないのが精神的にあまり良くないですね。どうせなら気持ちよくコーディングしたいものです。まあ、JSX自体が気持ち悪いという意見もありますがそれはまた別のお話。