I have two issues when using a FlatList (that both work with a ListView).
I have a list that is displayed via a display property for each item and then checked in my FlatList like so:
<FlatList
ref='flatList'
data={this.state.dataSource}
enableEmptySections
renderItem={({item}) => item.display && <Text>{item.text}</Text>} />
When I change the display property, it doesn't display however. This worked fine in the ListView setup.
My second problem is that scrollToEnd is firing an undefined error on "this._listref" which is within the scrollToEnd function. I pass no parameters to it.
setTimeout(this.refs.flatList.scrollToEnd, 0)
My questions are, how do I update the data in my array for the list so it changes in the list, and the second question is how do I fix the scrollToEnd error?
Update 1: (data removed, not needed anymore)
Update 2: Problem ONE solved, the list needs "extraData" comparison to see if it updates. The fixed edition:
<FlatList
ref='flatList'
data={this.state.dataSource}
extraData={this.state}
enableEmptySections
renderItem={({item}) => item.display && <Text>{item.text}</Text>} />
It's a bit convoluted, but I believe extraData acts as a comparison to see if anything in that data set updates. If so, re-render. That problem is solved.
"undefined is not an object (evaluating 'this._listRef')" still not fixed
Update 3: Scroll function works IF taken outside the setTimeoutfunction
Update 4:
Setting the initial data array
this.state = {
dataSource: pageService(state.params.page),
cursor: 0
}
Setting display as true:
renderNextModule() {
let newCursor = this.state.cursor
if (newCursor < this.state.dataSource.length-1) {
newCursor++
let newSource = this.state.dataSource
newSource[newCursor].display = true
this.setState({
dataSource: newSource,
cursor: newCursor
})
}
}
this._listRef
is undefined because setTimeout
calls the function and sets its context (this) to null.
As a workaround, you can actually use a wrapper function (here with ES6 syntax) :
setTimeout(() => this.refs.flatList.scrollToEnd(), 0)
Regarding your 1st problem, I don't think you're solving it the right way.
You were right that it uses a shallow comparison, but you might not need the extraData
prop.
Are you mutating your array directly? How are you updating the item.display
property?
For your 1st problem,
Replace this line
let newSource = this.state.dataSource
By this
let newSource = this.state.dataSource.slice()
In JavaScript, arrays are copied by reference, which means that you were not cloning the array but mutating it ; and as FlatList
is efficient (and this is for every PureComponent
), when you want to re-render it (by setting the state like you did), it does a ===
comparison on its old and new props to see if anything changed.
As you were mutating the old array, 'oldArray === newArray', so it was deciding to not update again.
This was a bit concise and fast but you can read more about why you need to create a new array with .slice()
here. This is true for arrays and objects in JavaScript.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With