2

React と ReFlux を利用するプロジェクトに取り組んでいます。現在、ReFlux ストアは 1 つだけですSubscriptionStore.js。これには、サブスクリプションに添付された各「タイトル」に関する詳細を含むネストされたオブジェクトの配列など、ユーザーのサブスクリプションに関する単純な詳細が含まれています。

背後にあるデータの簡単な内訳は次のSubscriptionStore.jsとおりです。

{
    hasThisSubcription: 0
    hasThatSubscription: 1
    nextPeriodStart: "2015-10-12"
    nextYearStartDate: "2016-09-12"
    accountTitles: [{
        id: "1"
        title: "The Name"
        createdDate: "2015-09-12 16:17:08"
    }, {
        id: "2"
        title: "Another Name"
        createdDate: "2015-09-12 16:17:08"
    }, {
        id: "3"
        title: "Yet Another Name"
        createdDate: "2015-09-12 16:17:08"
    }]
}

ユーザーが既存のタイトルの名前を更新したり、新しいタイトルを追加したり、タイトルを削除したりできる React コンポーネントがあります。追加と名前の変更はうまくいっていますが、削除は動作がおかしくて、React/ReFlux をまだ完全に把握していないためだと確信しています。

このメイン コンポーネントの関連コードは次のとおりです。

var React = require('react')
var Reflux = require('reflux')
var SubscriptionActions = require('../../stores/SubscriptionActions.js')
var SubscriptionStore = require('../../stores/SubscriptionStore.js')

module.exports = React.createClass({

    mixins: [
        Reflux.connect(SubscriptionStore, 'subscriptions')
    ],

    /**
     * Add new title
     * @param  {number} id The Title ID
     */
    addTitle() {
        SubscriptionActions.addNewTitle()
    },

    /**
     * Remove Title from state using on ID
     * @param  {number} id The Title ID
     */
    removeTitle(id) {
        SubscriptionActions.removeNewTitle(id)
    },

    /**
     * Update Title title using ID
     * @param  {number} id  The Title ID
     * @param  {string} value  The new title
     */
    saveTitle(id, value) {
        SubscriptionActions.updateNewTitle(id, value)
    },

    render() {

        // Check for Title subscriptions and create an editable field for each
        var theTitles = []
        for (var i = 0; i < this.state.subscriptions.accountTitles.length; i++) {
            theTitles.push(
                <EditableCapsule
                    key = {i}
                    ref = {'title' + i}
                    removable = {i === 0 ? false : true}
                    labelValue = ''
                    clickToRemove = {this.removeTitle.bind(this, i)}
                    primaryAction = {this.saveTitle.bind(this, i)}
                />
            )
        }

        return (
            <div>
                <ScrollArea ref='scrollArea'>
                    {theTitles}
                </ScrollArea>
            </div>
        )
    }
})

そして、からの関連するコードのビットSubscriptionStore.js:

removeTitle(id) {
    this.subscriptions.accountTitles = _.without(this.subscriptions.accountTitles, _.findWhere(this.subscriptions.accountTitles, { id: id }));
    this.trigger(this.subscriptions)
}

問題

どのタイトルをクリックして削除しても、削除されるのは常に最後のタイトルです。コンテンツの前後を吐き出すthis.subscriptions.accountTitlesと、正しいオブジェクトが実際にデータから削除されていることが示されますが、React は常に最後のアイテムが削除されているかのように要素をレンダリングしています。

何が起こっているのでしょうか?

4

1 に答える 1

3

使用しないでください<EditableCapsule key = {i} ...: の要点は、keyReact が更新、削除などの目的で使用する必要がある正確な要素の一意の識別子になることです。

配列内のその位置は、要素自体についてはまったく何も言っていないので、最初にそれを適切なキーに変更してください:

...

render: function() {
  var accountTiles = this.state.subscriptions.accountTitles; 
  var tileset = accountTiles.map(this.buildTiles);
  return <ScrollArea ref='scrollArea'>{ tileset }</ScrollArea>;
},

buildTiles: function(tile, position) {
  var identifier = tile.title + title.id;
  return (
    <EditableCapsule
      key = { identifier }
      ref = { identifier }
      removable = { position !== 0 }
      labelValue = ''
      clickToRemove = { this.removeTitle.bind(this, tile) }
      primaryAction = { this.saveTitle.bind(this, tile) }
    />;
  );
},
...

配列の位置に基づいて削除しないことにも注意してください。タイル自体に基づいて削除します。明らかな理由で。

于 2015-09-15T18:00:33.813 に答える