2017-04-24 7 views
2

イベントハンドラ関数が受け取ったオブジェクトのリストを表示するListViewを作成しようとしています。オブジェクトは非同期的に1度に1つ受信されます(ListViewDataSource documentationのシナリオに似ています)。非同期に更新されたオブジェクトのリストビュー

各オブジェクトには、IDフィールドと値フィールドがあります(特にこのフィールドには関係ありません)。 ListViewは各オブジェクトの両方のフィールドを表示します。

ハンドラは、IDは同じで値は異なる複数のオブジェクトを受け取ることができます。この場合、ListViewは新しい値でエントリを更新する必要があります。

ListViewに新しい項目を挿入するとうまくいきますが、既存の項目を更新するのではありません。どうやってするの?

今後の質問:ListViewの要素を値フィールドで並べ替えるにはどうすればよいですか?それを行う最善の方法は何ですか?

オブジェクトの

疑似(ISH)コード:コンポーネントの

class DataObj { 
    objid: string; 
    value: string; 

    static create(rawData: string) : ?DataObj { 
    if (Invalid data) return null; 

    let dataObj = new DataObj(); 
    dataObj.objid = ...; 
    dataObj.value = ...; 
    return dataObj; 
    } 

    static equal(lhs: DataObj, rhs: DataObj) { 
    return (lhs.objid === rhs.objid && lhs.value === rhs.value); 
    } 
} 

コード:以下のように

type State = { 
    items: ListView.DataSource, 
}; 

class MyComponent extends React.Component { 
    state: State; 

    _items = {}; 

    constructor(props: Props, context: {}) { 
    super(props, context); 

    const ds = new ListView.DataSource({ 
     rowHasChanged: (r1, r2) => !DataObj.equal(r1, r2) 
    }); 
    this.state = { 
     items: ds.cloneWithRows(this._items), 
    }; 
    } 

    _onNewItem = async (rawData: string) => { 
    const newItem = DataObj.create(rawData); 
    if (newItem) { 
     // Valid item 
     let oldItem = this._items[newItem.objid]; 
     if (!old || !DataObj.equal(oldItem, newItem)) { 
     // New item or updated item 
     // Clone _items, since it must be immutable, and add new item to it. 
     let newItems = Object.assign({}, this._items); 
     newItems[newItem.objid] = newItem; 
     // update _items reference to its modified clone. 
     this._items = newItems; 
     // Update the state 
     this.setState(({items}) => ({ 
      items: items.cloneWithRows(newItems), 
     })); 
     } 
    } 
    }; 

    render(): React.Element<*> { 
    return (
     <ListView 
     dataSource={this.state.items} 
     enableEmptySections={true} 
     renderRow={this._renderDataObj} /> 
    ); 
    } 

    _renderDataObj = (
    obj: DataObj, 
    sectionID: number, 
    rowID: number 
) : React.Element<*> => { 
    return (
     <DataObjRenderer 
     key={obj.objid} 
     objid={obj.objid} 
     value={obj.value} 
     /> 
    ); 
    } 
} 

答えて

0

ListViewを使用して問題を部分的に解決することは可能です。 アイテムのkeyプロパティには、再レンダリングの原因となるすべてのプロパティが含まれている必要があります。

ただし、すぐに廃止予定のリストビューを置き換えるFlatListを使用するのが最善の解決策です。 FlatListで同じキートリックを使用すると、私が持っていたすべての問題が解決されました。

0

W3C documentationによれば、次の配列をソートすることができる:

const points = [ 
    { 
     name: 'Alpha', 
     score: 40 
    }, 
    { 
     name: 'Bravo', 
     score: 100 
    }, 
    { 
     name: 'Charlie', 
     score: 1 
    } 
]; 

points.sort((a, b) => { 
    return a.score - b.score; 
}); 

Lodashを使用すると、クリーナーになります。

_.orderBy(points, ['user', 'age'], 
+0

実際には配列がソートされます。フォローアップの質問は、マップを使用してオブジェクトを格納し、必要に応じてオブジェクトを更新することです。それから、Array.from(this._items.values())という項目を持つ配列を取得する必要があります。それを並べ替える。しかしそれは別の問題を引き起こします:ReactはDataObjectのプロパティを変更すると無視します。 ListView要素のキーにすべての "observable"プロパティを追加しようとしました。しかし、それはうまく動作しません。 – Marcus

関連する問題