
これは少し特殊な使い方になるのかな?
私のサイトで配布しているGutebergに対応済みのプラグインには、ブロックを新規追加した際のパラメータ(初期値)を管理画面で予め設定変更できる物があります。
この機能をプラグインに盛り込もうと考えた際に気をつけるべきこと。
失敗したことを、この記事にまとめておきます。
簡単な実装方法
今回紹介する機能を盛り込もうと考えた場合、
attributesのdefaultを変数にしてあげれば簡単に実装することが出来ます。
attributes: {
title: {
type: "string",
default: default_value
}
}
外部から default_value
の値を
その都度変更すれば想定した機能を搭載できそうです。
思わぬ落とし穴
しかし思わぬところで落とし穴が…。
いざ管理画面から初期値を変更できる機能を搭載し、
弄ってみたら予期せぬ動作をするじゃないですか。
管理画面で初期値を変更したら、既に追加されている記事中のブロックまでattribute値が連動して変更される状態に。
簡単な例を上げれば、
attributes: {
color: {
type: "string",
default: default_color
}
}
上記のcolor値を設定し。
管理画面で初期値 default_color
を以下の3色に変更できるとします。
そして管理画面にて初期値redを指定し。
記事内にredを含んだブロックを複数追加しました。

その後、新しく追加するブロックの初期値はblueが良いかな?
と考え、管理画面から初期値をbuleに変更すると・・・。
以前記事にredとして追加したブロックがエラーを吐き出し、
何故か全てcolorの値がredからbuleへと一括変更されてしまいました。

何故でしょうか?
今回想定する動作を考えれば、
既に記事内に追加されているブロックのcolor値は影響を受けず
今後新規追加するブロックだけblueになるのが望んだ動作のはず。
原因はsaveのコメント値
どうしてこの様な想定した動作にならず、
既に追加したブロックまで影響を受けるのか?
attributesのdefault値は初期値なのだからブロックを追加した後は、
もう影響を受けないのが正常な動作のはず。
と考えて原因を探ってみると、
Gutenbergのブロックのパラメータ保存方法に問題がありました。
Gutenbergはブロック内で選んだパラメーターを
全てコメントとして保存する仕組みです。
<!-- wp:sample/blocks {"color":"red","content":"赤色のブロック"} -->
<div class="red">赤色のブロック</div>
<!-- /wp:sample/blocks -->
上記の様に にてパラメータ値を保存するのですが、ここで一つの落とし穴。
attributesでdefault値として
設定された値と、選択した値が一致する時、コメント欄に値は保存されない。
という仕様となっています。
<!-- wp:sample/blocks {"content":"赤色のブロック"} -->
<div class="red">赤色のブロック</div>
<!-- /wp:sample/blocks -->
<!-- wp:sample/blocks {"color":"blue","content":"青色のブロック"} -->
<div class="blue">青色のブロック</div>
<!-- /wp:sample/blocks -->
エラーが発生する原因
つまりdefault値を使って初期値変更を行っている場合。
管理画面でdefault値を変えると、saveの値とdefault値の値が変わり。
出力内容に齟齬が生じるためエラーが発生していたんですね。
既に下記のブロックが追加されていた状態で
<!-- wp:sample/blocks {"content":"赤色のブロック"} -->
<div class="red">赤色のブロック</div>
<!-- /wp:sample/blocks -->
colorがblueに変わると、初期値のcolor値がコメント欄に保存されていないため
<!-- wp:sample/blocks {"content":"赤色のブロック"} -->
<div class="blue">赤色のブロック</div>
<!-- /wp:sample/blocks -->
class="red"の部分がclass="blue"となるのです。
そしてこの現象をストップさせるためには
全てのパラメータを新規ブロック追加時にコメント欄に残る仕様にする。
つまりattributesのdefault値を使わないで
初期値を設定する仕組みにすれば良いという事です。
<!-- wp:sample/blocks {"color":"red","content":"赤色のブロック"} -->
<div class="red">赤色のブロック</div>
<!-- /wp:sample/blocks -->
colorの設定情報が内部で常に存在していれば問題ないという事です。
今回の落とし穴に対する解決策
初期値変更を行いたい値は
全てattributesのdefaultを使わずに指定する必要があるため、
edit()の部分で新規追加時の時のみ値を挿入する仕組みにしてあげましょう。
registerBlockType( 'sample/block', {
title: 'サンプルブロック',
icon: 'shield',
category: 'layout',
attributes: {
_first_load: {
type: "boolean",
default: false
},
color: {
type: "string"
},
content: {
type: "string",
default: ""
}
},
edit( { attributes, setAttributes } ) {
if (!attributes._first_load) {
setAttributes({
_first_load: true,
color: default_color,
content: "赤いブロック"
});
}
return (
<div className={attributes.color}>
{attributes.content}
</div>
);
},
save( { attributes } ) {
return (
<div className={attributes.color}>
{attributes.content}
</div>
);
}
} );
attributesに初回追加時に
判定値 _first_load
を設け、editで対応する方法です。
初回のみ if (!attributes._first_load) {}
内の処理が実行されるため、
ここで初期値を設定する方法ですね。
また今後初期値を設定するパラメータが増えた時、
setAttributesで一つ一つ設定するのが面倒なため、
初期値をobjectなどで渡してあげると4行で済みます。
Object.keys(DefaultValues).forEach((key) => {
if (attributes[key] === undefined) {
setAttributes({ key: DefaultValues[key] });
}
});
objectとして渡す方法は外部からjsonを読み込んだり、
色々とやり方はあると思うのですが、今回の記事では割愛します。
あなたの好きな方法で実装すると良いでしょう。
おわりに

今回説明した方法ですが、Gutenbergの新規ブロック追加時に初期値を設定したい。という機能を必要とする人はどれだけ居るのだろうか・・・?
少しマニアックな記事となっておりますが、attributesのdefalut値の動作。
コメント内部で保存される挙動は知らないと、ひょんな事からエラーを誘発するので頭の片隅にでも覚えておくと良いでしょう。