简体   繁体   中英

Use ref when props is ready

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:

  1. this.myRef is ready to use only in componentDidMount at the earliest.
  2. 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)
  3. In 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,
            });
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM