Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

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

こちらは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を変更すれば再マウントを走らせることができます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What are the problem?