5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Riot.jsAdvent Calendar 2017

Day 5

Riotの子要素のoptsの参照が変われば再マウントされる

Last updated at Posted at 2017-12-04

こちらはRiot.js Advent Calendar 2017の5日目の記事になります。業務でriotを使う中でハマった細かすぎて伝わらないtipsです。

コンポーネント更新時の挙動が自分のイメージと違っていて、ハマりました。
検証バージョンはv3.7.4です。

要素のループ

例えば、下記のような要素のループがあったとして、これは配列datasの中身を子要素に渡すよく見かけるものです。

<component each={v in datas} data={v}/>

this.datas = [
	{ value: 0 },
	{ value: 1 }
];

このリストのデータを更新したとします。

this.update({ 
	datas: [
		{ value: 2 },
		{ value: 3 }
	]
});

自分の中では、componentupdateだけ走って、再マウントはされないイメージでした。

実際には再マウントされる

codepenにサンプルを作りました。
子要素に渡すデータを更新しています。
https://codepen.io/kwst/pen/qVgedv

処理の順番としては下記のようになります。

  1. randomizeボタンを押す
  2. this.datasが変更される
  3. componentunmountが呼ばれる
  4. componentmountが呼ばれる
親コンポーネント
<component-template>
  <button onclick={this.randomize}>randomize datas</button>
  <component each={data in datas} data={data}/>
  this.datas = [
    { value: 0 },
    { value: 1 }
  ];
  
  this.randomize = () => {
    this.update({ datas: [
      { value: Math.random() },
      { value: Math.random() }
    ]});
  }
  
</component-template>
子コンポーネント
<component>
  <p>component {this.opts.data.value}</p>
  this.on('mount', () => { console.log('mount'); });
  this.on('unmount', () => { console.log('unmount'); });
</component>

参照が変わらない時(プリミティブな値の変更)では再マウントは走りませんでした。
https://codepen.io/kwst/pen/POVMdm

ちゃんとコードを読んだわけではありませんが、おそらく渡ってくるデータの参照が変われば別のコンポーネントとする仕様なのかもしれません。

自分のイメージでは、下記のように考えていました。子要素のshouldUpdateで更新すべきかどうかをハンドリングするのがスマートかなと思っていたので。

  1. randomizeボタンを押す
  2. this.datasが変更される
  3. componentshouldUpdateが呼ばれで、更新すべきかどうかを子要素側でハンドリングする
  4. shouldUpdateがtureであればcomponentを更新する

再マウントされないようにするには

3.7.xから追加されたkey属性を追加するだけでOKです。変更したい場合はkeyを変更すれば再マウントされます。リストのデータの一意なidなんかを割り当ててやると良いでしょう。

datasindex値をkeyに割り当ててみました。

親コンポーネント
<component each={data, i in datas} data={data} key={i}/>

追加したバージョン
https://codepen.io/kwst/pen/EbMVPX

ちなみにReactでは

ちなみにReactでは再マウントは走りませんでした。ただ自分がReactのメンタルモデルを引きずっていただけです。
https://codepen.io/kwst/pen/Zawgxq
Reactでもkeyを変更すれば再マウントを走らせることができます。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?