1
votes

I've made a chat app, and for rendering messages flatlist is used. But the problem is tried to scroll to the end of the screen every time the page is loaded, but it fails to do so. I've tried inverted props, but nothing happened, only the list got inverted.

Even played with ref to make it auto-scroll to the bottom, but nothing happened.

<FlatList
  ref="flatList"
  onContentSizeChange={() =>
    this.refs.flatList.scrollToEnd()}
  contentContainerStyle={{
    marginBottom:
      verticalScale(200)
  }}
  style={styles.list}
  data={this.state.messages}
/>

How to make it scroll to the bottom the screen or scroll to the last index of the message when rendered?

(UPDATE)

IT WAS AN ISSUE WITH THE <Content/> component i used which belongs to native-base . Upon removing and replacing it with a <View/> it works perfectly fine. Also, for chat based app the inverted prop in Flatlist is the way to implement in right way.

I've added the way i managed to scroll in the answer below. If you simply want your app to display the last item in the list and stays there, you can use inverted

5
Which version of react-native are you on? I have tried the following two examples in a fresh, empty RN 0.62 project: gist.github.com/mlisik/27165a6cf538d5ce3591d1da16afdbf5 They both work as intended (which would suggest your code should too). Side note: I don't think you really want to scroll to bottom every time you receive a new message. This should only happen when user is already scrolled down (otherwise they might not be able to read past messages) - and this case is actually handed out of the box with inverted FlatList. - Marek Lisik
it was an issue with the Content component i wrapped the Flatlist with. Fixed it by replacing it with a View. Thank you so much for your valuable time and help. - FortuneCookie

5 Answers

3
votes

You should use ref like this:

export default class MyAwesomeComponent extends React.Component {
  FlatListRef = null; // add a member to hold the flatlist ref

  render() {
    return (
      <FlatList
        ref={ref => (this.FlatListRef = ref)} // assign the flatlist's ref to your component's FlatListRef...
        onContentSizeChange={() => this.FlatListRef.scrollToEnd()} // scroll it
        contentContainerStyle={{marginBottom: verticalScale(200)}}
        style={styles.list}
        data={this.state.messages}
      />
    );
  }
}
2
votes

prueba esto

return (
      <View style={{flex: 1}}>
        <KeyboardAvoidingView
          behavior="padding"
          style={styles.keyboard}
          keyboardVerticalOffset={height - 1000}>
          <FlatList
            ref={ref => (this.FlatListRef = ref)}
            onContentSizeChange={() => this.FlatListRef.scrollToEnd()} // scroll it
            // contentContainerStyle={{marginBottom: verticalScale(200)}}
            // keyboardShouldPersistTaps='always'
            style={styles.list}
            extraData={this.state}
            data={this.state.messages}
            keyExtractor={item => {
              return item.id;
            }}
            renderItem={e => this._renderItem(e)}
          />
          <View style={styles.input}>
            <TextInput
              // style={{flex: 1}}
              value={msg}
              placeholderTextColor="#000"
              onChangeText={msg => this.setState({msg: msg})}
              blurOnSubmit={false}
              onSubmitEditing={() => this.send()}
              placeholder="Escribe el mensaje"
              returnKeyType="send"
            />
          </View>
        </KeyboardAvoidingView>
      </View>
    );
0
votes

You can use Javascript method to reverse to show your messages from end

messages.reverse()
0
votes
scrollToListPosition = (index) => {
  const itemOffset = this.getItemOffset(index)
  this.flatListRef.scrollToOffset({ animated: false, offset: itemOffset })
}

getItemOffset = (index) => {
  let heightsum = 0
  for (i = 0; i < index; i++) {
    heightsum = heightsum + this.itemHeight[i]
  }
  return heightsum
}


render(){
  return (
    <FlatList
      ref={(ref) => { this.flatListRef = ref; }}
      data={postList}
      keyExtractor={(item, index) => item._id}
      horizontal={false}
      extraData={this.state}
      keyboardShouldPersistTaps='always'
      refreshing={this.props.isRefreshing}
      onRefresh={this.handleRefresh}
      onEndReached={this.handleLoadMore}
      getItemLayout={(data, index) => (
        { length: this.getLength(index), offset: this.getLength(index) * index, index }
      )}
      renderItem={({ item, index }) => {
        return (
          <View onLayout={(event) => {
            var { height } = event.nativeEvent.layout;
            this.itemHeight[index] = height
          }}
          >
            <ListCommon
              key={index}
              item={item}
              index={index}
              parentFlatList={this}
              data={item}
              instance={this.props.commanAction}
              tag={this.state.tag}
              changeRoute={this.props.changeRoute}
            />
          </View>
        );
      }}
    />
  )
}

getLength = (index) => {
  if (this.itemHeight[index] === undefined) {
    return 0;
  }
  return this.itemHeight[index]
}
0
votes

Here is how i solved it:

export default class Test extends Component {
  constructor(props) {
    super(props);
  }
  componentDidMount() {
    setTimeout(() => {
      this.FlatListRef.scrollToEnd();
    }, 1500);
  }
  render() {
    return (
      <View style={{ flex: 1 }}>
        <FlatList
          data={[1, 2, 3, 4, 5, 6, 7, 8]}
          ref={(ref) => (this.FlatListRef = ref)}
          renderItem={({ item }) => {
            return (
              <View
                style={{
                  height: 140,
                  width: 400,
                  backgroundColor: "yellow",
                  alignItems: "center",
                  justifyContent: "center",
                }}
              >
                <Text>{item}</Text>
              </View>
            );
          }}
        />
      </View>
    );
  }

}