export default class Test extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
}
componentDidMount() {
if (this.props.data.length) {
this.myRef.current.scrollToIndex({
index: this.props.index,
});
}
}
render() {
return (
<FlatList
ref={this.myRef}
data={this.props.data}
renderItem={this.renderItem}
getItemLayout={(data, index) => ({
length: 50,
offset: 100 * index,
index,
})}
/>
);
}
}
Goal:
As soon as the component renders, the FlatList should automatically scroll down to an item which has index === this.props.index
(Imagin an instant messaging app, where you want to automatically scroll down to a message)
Issue:
Either this.myRef
or this.props.data
is undefined.
Observation:
this.myRef
is ready to use only in componentDidMount
at the earliest.this.props
is undefined in componentDidMount
since it takes time
to have this.props
read to use (By ready
I mean, has values, is defined)getDerivedStateFromProps
I checked to see if this.props
is ready, however, this.myRef
was still undefined. (Maybe it is too soon for it to get initialized)How can I achieve my goal?
System:
OS: macOS 10.15.3
CPU: (4) x64 Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz
Memory: 122.77 MB / 8.00 GB
Shell: 5.7.1 - /bin/zsh
Binaries:
Node: 12.13.1 - ~/.nvm/versions/node/v12.13.1/bin/node
npm: 6.12.1 - ~/.nvm/versions/node/v12.13.1/bin/npm
Watchman: 4.9.0 - /usr/local/bin/watchman
SDKs:
iOS SDK:
Platforms: iOS 13.2, DriverKit 19.0, macOS 10.15, tvOS 13.2, watchOS 6.1
Android SDK:
API Levels: 28, 29
Build Tools: 28.0.3, 29.0.2
System Images: android-28 | Google APIs Intel x86 Atom, android-29 | Google APIs Intel x86 Atom
IDEs:
Android Studio: 3.5 AI-191.8026.42.35.5977832
Xcode: 11.3.1/11C504 - /usr/bin/xcodebuild
npmPackages:
react: 16.9.0 => 16.9.0
react-native: https://github.com/expo/react-native/archive/sdk-36.0.1.tar.gz => 0.61.4
componentDidMount
is only called once after the first render but if your data is not ready then you won't have a second chance to scroll down.
You should remove your componentDidMount
and replace it with componentDidUpdate
to handle a change in props.data:
componentDidUpdate(prevProps) {
if (this.props.data !== prevProps.data) {
if (this.props.data.length) {
this.myRef.current.scrollToIndex({
index: this.props.index,
});
}
}
}