14

Working with React Native, having some issues with the FlatList component. This is my FlatList

    <FlatList
     data={this.state._data}
     renderItem={() => this.renderItem()}
     refreshControl={
       <RefreshControl
        onRefresh={() => this.handleRefresh}
        refreshing={this.state.refreshing}
       />
      }
    />

This is my renderItem function:

    renderItem({item, index}) {
     return (
      <View style={{marginTop: 10, marginHorizontal: 10, paddingLeft: 
         10}}>
        <ListItem
            roundAvatar
            title={`${item.itemName}`}
            subtitle={`${item.amount}`}
            avatar={require('../../../images/logo.png')}
        />
        <View
            style={{
                paddingBottom: 10,
                paddingTop: 10,
                display: 'flex',
                flexDirection: "row",
                justifyContent: "space-around",
                alignContent: "center"
            }}
         >
            <View style={{ flexDirection: "row", alignContent: 
                 "center", width:"45%"}}>
                <Button
                    block
                    small
                    // disabled={this.state.acceptButtonGray}
                    style=
                      {this.state.acceptButtonGray ? ({
                      backgroundColor: 'gray',
                      width: "100%"
                      }) : ({backgroundColor: "#369ecd",
                         width: "100%"
                      })}
                    onPress={() =>
                      this.setState({
                         modalVisible: true,
                         // acceptOrDeclineModalText: `Accept offer for ${item.amount} ${'\b'} Are you Sure?`,
                         acceptOffer: true,
                          })
                      }
                      >
                    <Text>
                        Accept
                    </Text>
                </Button>
            </View>
        </View>
    </View>
   );
  }

this.setState in the onPress in the button should make a Modal visible, and set acceptOffer to true. Modal opens, user confirms their offer. The offer button which opened that modal now should be gray, and even better, disabled.

Passing my RenderItem function as shown above, I receive

    TypeError: Cannot read property 'item' of undefined.

Passing my RenderItem function like this:

    renderItem={this.renderItem}

I Get This Error:

    _this2.setState is not a function

The FlatList Component is certainly responsible for part of my issue, as well as how and where I am calling this.setState. Only one button is shown in my post, but there are two, one for accept, one for decline. Would having two modals change anything?

The FlatList displays my ListItem components with ease until I attempt to call this.setState in the buttons inside the View which contains those ListItems.

The Modal close button takes this.state.acceptOffer and if true, sets this.state.acceptButtonGray to true, should this logic be somewhere else?

Is there another way to open a modal and change the button color without using component state? Does react want these buttons inside of a TouchableOpacity?

I greatly appreciate any help given.

HarshitMadhav
  • 4,769
  • 6
  • 36
  • 45
  • i would recommend you to use FlatList with Pure Component and u will resolve this error too . https://facebook.github.io/react-native/docs/flatlist.html . Example is given over here – Devansh sadhotra Dec 22 '17 at 07:46

6 Answers6

26

you should write a renderItem function like this

renderItem = ({item, index}) => {
 // return here
}
Shubham
  • 740
  • 12
  • 33
  • This solution worked, I sort of know why, but not really. Care to explain? – falconsAndFunctions Dec 22 '17 at 18:57
  • all function of the component should be bind if you want to use them. This is required as in the reactjs official documentation. – Shubham Dec 26 '17 at 13:03
  • renderItem is assigned an arrow function which always maintains the current "this" at the time of assignment which is why the arrow function is awesome – King Friday Apr 06 '18 at 02:59
5

As per my Knowledge item and index are passed as object in flatlist's renderItem

so we can pass by two ways

1 way

Flatlist Component

<FlatList
     data={this.state.data}
     keyExtractor={(item, index) => index.toString()}
     renderItem={({ item, index }) => this._renderItem(item, index)} //Passing as object from here.
/>

Render Item

_renderItem = (item, index) => {
      console.log(item)
      console.log(index)
}

2 way

Flatlist Component

<FlatList
     data={this.state.data}
     keyExtractor={(item, index) => index.toString()}
     renderItem={( item, index ) => this._renderItem(item, index)}
/>

Render Item

_renderItem = ({item, index}) => { // Passing as object from here
      console.log(item)
      console.log(index)
}
Hardik Desai
  • 1,089
  • 12
  • 20
4

Change your renderItem method to renderItem={this.renderItem.bind(this)}?

Marcos Demétrio
  • 1,337
  • 9
  • 12
2

1) You can write function as -

renderItem = ({item, index}) => { // return here }

2) or else if you want to execute your function then -

<FlatList
 data={this.state._data}
 renderItem={(item) => this.renderItem.bind(this, item)}
 refreshControl={
   <RefreshControl
    onRefresh={() => this.handleRefresh}
    refreshing={this.state.refreshing}
   />
  }
/>
Samiksha Jagtap
  • 585
  • 2
  • 13
  • 29
  • 1
    I am not sure why this answer is in at minus one .. but at some point this helped me and saved my time. – NMathur Apr 04 '19 at 07:10
2

You have to use bind(this,item) or change function like (item)=>.

anothernode
  • 5,100
  • 13
  • 43
  • 62
Amin Noura
  • 289
  • 2
  • 12
2

I experienced the same issue and wasted many hours to figure out why it was not re-rendering:

We need to set extraData prop of FlatList if there is any change in the state like so:

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

Please see the official documentation here:

https://facebook.github.io/react-native/docs/flatlist.html

atulkhatri
  • 10,896
  • 3
  • 53
  • 89