フラットリストを再レンダリングする方法は?


88

ListViewとは異なり、this.state.datasourceを更新できます。FlatListを更新または再レンダリングする方法や例はありますか?

私の目標は、ユーザーがボタンを押したときにテキスト値を更新することです...

renderEntries({ item, index }) {
    return(
        <TouchableHighlight onPress={()=> this.setState({value: this.state.data[index].value+1})>
             <Text>{this.state.data[index].value}</Text>
        </TouchableHighlight>
    )
}

<FlatList 
    ref={(ref) => { this.list = ref; }} 
    keyExtractor={(item) => item.entry.entryId} 
    data={this.state.data} 
    renderItem={this.renderEntries.bind(this)} 
    horizontal={false} />

8
FlatListドキュメントには、「これは、PureComponent小道具が浅いままの場合は再レンダリングされないことを意味します。renderItem関数が依存するすべてのものが、===更新後ではない小道具として渡されることを確認してください。そうしないと、UIが更新されない可能性があります。変更時。これには、data小道具と親コンポーネントの状態が含まれます。」このアドバイスに従っていますか?
ジョーダンランニング

3
何を試してextraDatashouldItemUpdate、リストを再レンダリングできませんでした。私がやったことは、状態をクリアし、それがレンダリングされるのを待ってから、状態を更新することでした。this.setState({ data: null }, () => { this.setState({ data: actualData }) });
Joshua Pinter 2017

回答:


193

extraDataFlatListコンポーネントのプロパティを使用します。

ドキュメントに記載されているように:

に渡すextraData={this.state}ことで、変更時に自分自身を再レンダリングFlatListすることを確認FlatListstate.selectedます。この小道具を設定しFlatListないと、アイテムを再レンダリングする必要があることを知りません。これもaでPureComponentあり、小道具の比較では変更が表示されないためです。


36
私はreduxを使用しており、その場合、のようなデータを送信していますがdata={this.props.searchBookResults}、どちらextraData={this.state}extraData={this.props}機能していません。そして、data={this.props.searchBookResults}あまりにも機能していません。何をすべきか ?
Sujit 2017年

11
使用extraData:あなたの<FlatList>リフレッシュする... data={this.props.searchBookResults} extraData={this.state.refresh} onPress={()={this.setState({ refresh: !refresh})}
いや

9
私は同じ問題に苦しんでいます。私が何を渡すかは関係ありませんextraData、コンポーネントは更新されません:(
Denis Cappelini 2017

2
@DenisCappelini、extraData子アイテムを再レンダリングする必要があるときに、小道具に渡されるデータが変更されることを確認してください。たとえば、リストアイテムをアクティブ/非アクティブにできる場合は、this.stateオブジェクトの一部であるかthis.propsオブジェクトの一部であるかに関係なく、ステータス変数が内部にあることを確認してくださいextraData。これは、カーソル、またはアクティブなアイテムなどのアレイであるかもしれない
Emperor_Earth

1
@Sujit同じ問題が発生していましたがshouldComponentUpdate()、実装したことに気付きました。それを更新するか、完全にコメントアウトすると、ドキュメントに記載されているとおりに機能していました。
JanithaR

54

迅速で簡単な解決策については、以下を試してください。

  1. 追加のデータをブール値に設定します。

    extraData = {this.state.refresh}

  2. リストを再レンダリング/更新する場合は、ブール状態の値を切り替えます

    this.setState({ 
        refresh: !this.state.refresh
    })
    

データプロップにデータを追加するので、まさにそれが必要です。また、これはReact-Nativeチームによる非常に奇妙な実装です...データに更新関数またはプロパティを設定する方が理にかなっています。IE :this.data.refresh()。代わりに、ブール値を設定して変更します。ブール値自体には意味がないので、その中に存在するポイントは何ですか?...(データを正しく更新する以外にポイントはありませんか?)
YungGun19年

@HradeshKumarやりましたが、データ内の最後のアイテムが消えることはありません!
四天王

これは魅力のようにthis.state.users機能しますが、一部のユーザーでフラグを変更していたにもかかわらず、なぜ機能しなかったのかはまだわかりません。
shyammakwana.me

あなたが助けをしてくださいすることができ、私のために動作しません:stackoverflow.com/questions/65547030/...
ガヤトリDipali

21

ああ、それは簡単です、ただ使うだけです extraData

追加データが舞台裏でどのように機能するかは、FlatListまたはVirtualisedListが、オブジェクトが通常のonComponentWillReceivePropsメソッドで変更されたどうかをチェックするだけであることがわかります

したがって、あなたがしなければならないのは、に変更する何かを与えることを確認することだけですextraData

これが私がすることです:

私はimmutable.jsを使用しているので、見たいものをすべて含むMap(不変オブジェクト)を渡すだけです。

<FlatList
    data={this.state.calendarMonths}
    extraData={Map({
        foo: this.props.foo,
        bar: this.props.bar
    })}
    renderItem={({ item })=>((
        <CustomComponentRow
            item={item}
            foo={this.props.foo}
            bar={this.props.bar}
        />
    ))}
/>

このように、不変オブジェクトは以前のものとは異なるため、変更時this.props.fooまたはthis.props.bar変更時CustomComponentRowに更新されます。


2
やっとわかりましたextraDataVirtualisedListコードへのリンクをありがとう!
Tushar Koul 2018

こんにちは、SudoPiz I @このQチェックすることができ、最後の項目を削除した後に再レンダリングFlatlistにしたいstackoverflow.com/questions/58780167/...を
オリバーD

6

OK。FlatListにデータプロパティの外部のデータ変更を認識させたい場合は、extraDataに設定する必要があることがわかったので、今は次のようにします。

<FlatList data={...} extraData={this.state} .../>

参照:https//facebook.github.io/react-native/docs/flatlist#extradata


2
最良の実装...データプロップと同じように設定することを好みました。そのため、状態が変更されても更新されませんが、これははるかに簡単な実装です。ありがとう!
ロバートキーホー

こんにちは、@MahdiBashirpour私は最後の項目を削除した後Flatlistを再レンダリングしたい、このQの確認することができますstackoverflow.com/questions/58780167/...
オリバーD

4

Buttonを使用する場合は、onPress内のsetStateを使用してデータを更新できます。その後、SetStateはFlatListを再レンダリングします。


3
touchablehighlightにsetStateがあります。setStateは正常に機能していますが、フラットリストに状態値の更新が表示されていません-> this.state.value
shalonteoh

データソースを直接更新していないため、FlastListの値は更新されていません。this.state.dataはFlatListでレンダリングされるものですが、onPressではthis.state.valueのみを更新しています。
WilliamC 2017

申し訳ありませんが、タイプミスです。this.state.data [index]
.value

4

たくさんの検索と本当の答えを探した後、最終的に私はそれが最高だと思う答えを得ました:

       <FlatList
      data={this.state.data}
      renderItem={this.renderItem}
      ListHeaderComponent={this.renderHeader}
      ListFooterComponent={this.renderFooter}
      ItemSeparatorComponent={this.renderSeparator}
      refreshing={this.state.refreshing}
      onRefresh={this.handleRefresh}
      onEndReached={this.handleLoadMore}
      onEndReachedThreshold={1}
      extraData={this.state.data}
      removeClippedSubviews={true}
      **keyExtractor={ (item, index) => index }**
              />
    .....

私の主な問題は(KeyExtractor)私はこのようにそれを使用していませんでした。動作しません:keyExtractor = {(item)=> item.ID}これに変更した後、それは魅力のように動作しました。これが誰かに役立つことを願っています。


this.state.refreshingと関数の値を入れることができますhandleRefreshか?
四天王

2

ここで前の答えの単なる拡張。確実にする2つの部分。extraDataを追加することと、keyExtractorが一意であることを確認してください。keyExtractorが一定の場合、再レンダリングはトリガーされません。

<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
                                    </FlatList>

1

追加することでこの問題を解決extraData={this.state}しました詳細については以下のコードを確認してください

render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={this.state.arr}
          extraData={this.state}
          renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
        />
      </View>
    );
  }

0

に交換FlatListしましたがSectionList、状態が変わると正しく更新されます。

<SectionList
  keyExtractor={(item) => item.entry.entryId} 
  sections={section}
  renderItem={this.renderEntries.bind(this)}
  renderSectionHeader={() => null}
/>

覚えておく必要があるのsectionは、diff構造を持つことだけです。

const section = [{
  id: 0,
  data: this.state.data,
}]

0

私にとっての秘訣は、extraDataとアイテムコンポーネントへのドリルダウンでした。

state = {
  uniqueValue: 0
}

<FlatList
  keyExtractor={(item, index) => item + index}
  data={this.props.photos}
  renderItem={this.renderItem}
  ItemSeparatorComponent={this.renderSeparator}
/>

renderItem = (item) => {
  if(item.item.selected) {
    return ( <Button onPress={this.itemPressed.bind(this, item)}>Selected</Button> );
  }
  return ( <Button onPress={this.itemPressed.bind(this, item)}>Not selected</Button>);
}

itemPressed (item) {
  this.props.photos.map((img, i) => {
    if(i === item.index) {
      if(img['selected') {
        delete img.selected;
      } else {
        img['selected'] = true;
      }
      this.setState({ uniqueValue: this.state.uniqueValue +1 });
    }
  }
}

0

インタラクションによって変更される変数を extraData

あなたは創造的になることができます。

たとえば、チェックボックスが付いた変化するリストを扱っている場合です。

<FlatList
      data={this.state.data.items}
      extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
      renderItem={({item}) => <View>  


0

react-native-flatlistでは、これらはextraDataと呼ばれるプロパティです。以下の行をフラットリストに追加します。

 <FlatList
          data={data }
          style={FlatListstyles}
          extraData={this.state}
          renderItem={this._renderItem}
       />

0

この例では、再レンダリングを強制するには、変数を変更するだけです。 machine

const [selected, setSelected] = useState(machine)

useEffect(() => {
    setSelected(machine)
}, [machine])

-1

使用するだけ:

onRefresh={true}

flatListコンポーネント内。


1
これは、エラーを生成し、uは使用し、その後必要なrefreshing小道具
mahmoudafer

-1

FlatlistのextraDataが機能せず、たまたまreduxの小道具を使用していました。これは、ED209の回答のコメントからの問題と同様に聞こえました。小道具を受け取ったときに手動でsetStateを呼び出すことになりました。

componentWillReceiveProps(nextProps: StateProps) {
    if (this.props.yourProp != null && nextProps.yourProp) {
        this.setState({ yourState: processProp(nextProps.yourProp) });
    }
}


<FlatList
  data={this.state.yourState}
  extraData={this.state.yourState}
/>

> React 17を使用している場合は、getDerivedStateFromPropsを使用してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.