[reactjs] How to re-render flatlist?

Unlike ListView we can update this.state.datasource. Is there any method or example to update FlatList or re-render it?

My goal is to update the text value when user press button ...

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} />

This question is related to reactjs react-native react-native-flatlist

The answer is


OK.I just found out that if we want the FlatList to know the data change outside of the data prop,we need set it to extraData, so I do it like this now:

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

refer to : https://facebook.github.io/react-native/docs/flatlist#extradata


I solved this problem by adding extraData={this.state} Please check code below for more detail

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

Flatlist's extraData wasn't working for me and I happened to be using a prop from redux. This sounded similar to issues from the comments in ED209's answer. I ended up manually calling setState when I receive the prop.

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}
/>

For those of you using > React 17 use getDerivedStateFromProps


For me, the trick was extraData and drilling down into the item component one more time

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 });
    }
  }
}

Just use:

onRefresh={true}

inside your flatList component.


Oh that's easy, just use extraData

You see the way extra data works behind the scenes is the FlatList or the VirtualisedList just checks wether that object has changed via a normal onComponentWillReceiveProps method.

So all you have to do is make sure you give something that changes to the extraData.

Here's what I do:

I'm using immutable.js so all I do is I pass a Map (immutable object) that contains whatever I want to watch.

<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}
        />
    ))}
/>

In that way, when this.props.foo or this.props.bar change, our CustomComponentRow will update, because the immutable object will be a different one than the previous.


In this example, to force a re-render, just change the variable machine

const [selected, setSelected] = useState(machine)

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

after lots of searching and looking for real answer finally i got the answer which i think it is the best :

       <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 }**
              />
    .....

my main problem was (KeyExtractor) i was not using it like this . not working : keyExtractor={ (item) => item.ID} after i changed to this it worked like charm i hope this helps someone.


I am using functional component, in that I am using Flatlist with redux data. I am managing all the state with Redux store. Here is the solution to update the Flatlist data after the api call.

I was first doing like this:-

const DATA  = useSelector((state) => state.address.address);


<FlatList
    style = {styles.myAddressList}
    data = {DATA}
    renderItem = {renderItem}
    keyExtractor = {item => item._id}
    ListEmptyComponent = {EmptyList}
    ItemSeparatorComponent={SeparatorWhite}
    extraData = {refresh}
    
    />

but the data was not re-rendering my Flatlist data at all.

As a solution I did like given Below:-

<FlatList
    style = {styles.myAddressList}
    data = {useSelector((state) => state.address.address)}
    renderItem = {renderItem}
    keyExtractor = {item => item._id}
    ListEmptyComponent = {EmptyList}
    ItemSeparatorComponent={SeparatorWhite}
    />

I am passing the Redux state directly to the Flatlist Datasource rather than allocating it to the variable.

Thank you.


If you are going to have a Button, you can update the data with a setState inside the onPress. SetState will then re-render your FlatList.


If we want the FlatList to know the data change both prop and state,we can construct an object referencing both prop and state and refresh the flatlist.

const hasPropOrStateChange = { propKeyToWatch: this.props, ...this.state};
<FlatList data={...} extraData={this.hasPropOrStateChange} .../>

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


I have replaced FlatList with SectionList and it is updates properly on state change.

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

The only thing need to keep in mind is that section have diff structure:

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

For quick and simple solution Try:

  1. set extra data to a boolean value.

    extraData={this.state.refresh}

  2. Toggle the value of boolean state when you want to re-render/refresh list

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

Just an extension on the previous answers here. Two parts to ensure, Make sure that you add in extraData and that your keyExtractor is unique. If your keyExtractor is constant a rerender will not be triggered.

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

In react-native-flatlist, they are a property called as extraData. add the below line to your flatlist.

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

Put variables that will be changed by your interaction at extraData

You can be creative.

For example if you are dealing with a changing list with checkboxes on them.

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

Examples related to reactjs

Error: Node Sass version 5.0.0 is incompatible with ^4.0.0 TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined raised when starting react app Template not provided using create-react-app How to resolve the error on 'react-native start' Element implicitly has an 'any' type because expression of type 'string' can't be used to index Invalid hook call. Hooks can only be called inside of the body of a function component How to style components using makeStyles and still have lifecycle methods in Material UI? React Hook "useState" is called in function "app" which is neither a React function component or a custom React Hook function How to fix missing dependency warning when using useEffect React Hook? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release

Examples related to react-native

How to resolve the error on 'react-native start' React Native Error: ENOSPC: System limit for number of file watchers reached How to update core-js to core-js@3 dependency? Unable to load script.Make sure you are either running a Metro server or that your bundle 'index.android.bundle' is packaged correctly for release error Failed to build iOS project. We ran "xcodebuild" command but it exited with error code 65 How can I force component to re-render with hooks in React? What is useState() in React? Getting all documents from one collection in Firestore ReactJS: Maximum update depth exceeded error React Native: JAVA_HOME is not set and no 'java' command could be found in your PATH

Examples related to react-native-flatlist

How to re-render flatlist?