23
15

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.

[React Native]FlatListのdataを変更しても画面が更新されない

Last updated at Posted at 2017-10-05

ReactNativeのFlatListではまった話

背景

  • FlatListのdataをstateで管理してリストの項目数を動的に変更しようとした
  • だけどstateを更新しても画面は更新されない

うまくいかない状態

  • うまくいかないサンプル
  • 追加ボタンを押す度にlistに一件追加されるが表示に変化は起きない

before.gif

App.js
import React, { Component } from 'react';
import { Button, FlatList, StyleSheet, Text, View } from 'react-native';

export default class App extends Component<{}> {
  constructor(props) {
    super(props);
    // listの初期値は一件
    this.state = { list: [{ key: new Date().toString() }] };
  }

  componentWillUpdate() {
    // stateが更新される度にlistが更新されていることが確認できる
    alert(JSON.stringify(this.state.list));
  }

  onPress() {
    // listに一件追加している
    const tmp = this.state.list;
    tmp.push({ key: new Date().toString() });
    this.setState({ list: tmp });
  }

  renderItem({ item }) {
    return (
      <View style={styles.itemContainer}>
        <Text>{ item.key }</Text>
      </View>
    );
  }

  render() {
    return (
      <View style={styles.container}>
        <Button title="追加" onPress={this.onPress.bind(this)} />
        <FlatList data={this.state.list} renderItem={this.renderItem} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: 'white',
    flex: 1,
    paddingHorizontal: 10,
    paddingVertical: 25,
  },
  itemContainer: {
    backgroundColor: 'lightblue',
    paddingHorizontal: 30,
    paddingVertical: 10,
    margin: 5,
  },
});

解決策

  • FlatListにexecDataを渡してその値も毎回更新するようにするとうまくいく

after.gif

App.js
import React, { Component } from 'react';
import { Button, FlatList, StyleSheet, Text, View } from 'react-native';

export default class App extends Component<{}> {
  constructor(props) {
    super(props);
    this.state = {
      list: [{ key: new Date().toString() }],
      listUpdate: 0, // 画面を再描画するためだけに使うstate
    };
  }

  componentWillUpdate() {
    alert(JSON.stringify(this.state.list));
  }

  onPress() {
    const tmp = this.state.list;
    tmp.push({ key: new Date().toString() });
    this.setState({
      list: tmp,
      listUpdate: this.state.listUpdate + 1 // list更新のタイミングでこっちも更新
    });
  }

  renderItem({ item }) {
    return (
      <View style={styles.itemContainer}>
        <Text>{ item.key }</Text>
      </View>
    );
  }

  render() {
    return (
      <View style={styles.container}>
        <Button title="追加" onPress={this.onPress.bind(this)} />
        {/* execDataを追加 */}
        <FlatList data={this.state.list} execData={this.state.listUpdate} renderItem={this.renderItem} />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: 'white',
    flex: 1,
    paddingHorizontal: 10,
    paddingVertical: 25,
  },
  itemContainer: {
    backgroundColor: 'lightblue',
    paddingHorizontal: 30,
    paddingVertical: 10,
    margin: 5,
  },
});

解説

  • FlatListの再描画はdataとexecDataのどちらかの値が「変化」したら行われるらしい
  • ただし、その「変化」したの確認はlistの要素が変化したのは検知しないらしい
  • だから確実に「変化」したと扱われるような値をexecDataにセットすると再描画される

あとがき

  • コードレベルで追えてないので確認したら追記する
23
15
2

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
23
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?