merry-go-round
merry-go-round

Reputation: 4615

FlatList item doesn't update when I setState()

I'm building multiple select modal. When user press the item, the item should be marked as 'Checked'.

Problem I added/removed id from id arrays. When I open and check modal, it doesn't show 'Check' sign. But when I close and open the modal again, it shows 'Check' Sign.

enter image description here

To keep track of selected items, I defined the items in the modal component's state.

  state = {
    selectedSeasonIds: this.props.selectedSeasonIds,
   }

Here is react-native-modal which I use to show modal on the screen

<Modal
      isVisible={isSelectorVisible}
      onBackdropPress = {() => this.props.hideSelector()}>
      <View style={styles.modalContainer}>
          <FlatList
              style={styles.root}
              data={this.props.items}
              ItemSeparatorComponent={this._renderSeparator}
              keyExtractor={this._keyExtractor}
              renderItem={this._renderItemForMultiple}/>
      </View>
</Modal>

This is render function for each item

_renderItemForMultiple = ({item}) => {
    return (
      <TouchableOpacity
        style={styles.itemStyle}
        onPress={() => {this._handleMultipleItemPress(item.id)}}>
        <RkText>{item.value}</RkText>
        { this._renderCheck(item.id) }   <<< Here is the problem
      </TouchableOpacity>
    );
  }

When user clicks the item, FlatList's item calls _handleMultipleitemPress

  _handleMultipleItemPress = (id) => {
    let { selectionType } = this.props;
    let { selectedSeasonIds, selectedSizeIds, selectedColorIds } = this.state;
    if(selectionType===2) {
      if(_.includes(this.state.selectedSeasonIds, id)) {
        let newSelectedSeasonIds = _.filter(this.state.selectedSeasonIds, (curObject) => {
            return curObject !== id;
        });
        this.setState({selectedSeasonIds : newSelectedSeasonIds});
      } else {
        let newSelectedSeasonIds = [...this.state.selectedSeasonIds, id];
        this.setState({selectedSeasonIds : newSelectedSeasonIds});
      }
    }
    // season Select Action
    this.props.seasonSelectAction(id);
  }

Problem We added/removed id from id arrays. When I open and check modal, it doesn't show 'Check' sign. But when I close and open the modal again, it shows 'Check' Sign.

Somehow the modal is not rendered even eventhough we setState in renderCheck(). Why is it happening? And How can I fix it?

  _renderCheck = (id) => {
    let { selectionType, selectedSeasonIds, selectedSizeIds, selectedColorIds } = this.props;
    if(selectionType===2) {
      if(_.includes(this.state.selectedSeasonIds, id)) {
        return (<RkText>Check </RkText>);
      }
    } 
    return (<RkText> </RkText>);
  }

Any other advice will be also appreciated! Thanks for reading this post.

UPDATE I debugged with code and when I press the item, it doesn't go through _renderItemForMultiple. I think it's because I didn't define a param for _renderItemForMultiple. How can I pass item to its param? Any idea?

Upvotes: 3

Views: 4101

Answers (1)

Andy
Andy

Reputation: 8640

Even though your state changes, you're not passing it to <FlatList>, so its props don't change. Its shouldComponentUpdate method returns false when none its props change. As the docs state:

By passing extraData={this.state} to FlatList we make sure FlatList itself will re-render when the state.selected changes. Without setting this prop, FlatList would not know it needs to re-render any items because it is also a PureComponent and the prop comparison will not show any changes.

So you need to pass extraData={this.state} to FlatList.

Upvotes: 6

Related Questions