每次我在TextInput中输入内容时,FlatList都会重新渲染

时间:2018-05-22 11:26:26

标签: javascript performance react-native

我不认为这是一个错误,更像是我做错了什么但是就在这里。 我正在为我的应用程序构建一个聊天组件,它非常简单,我输入了一些按下发送按钮添加到列表和显示。 几天前我发现,如果我开始输入大而快的消息,我的JS FPS会下降到10,5甚至1,我今天发现了,因为每次我在TextInput中输入内容时都会实现消息的数据/时间显示并运行onChangeText事件并更改“text”的状态,它重新呈现我的FlatList中的所有项目

这是我的代码:

聊天组件:

<FlatList
    key={'chat'}
    ref={(ref) => {flatlistRef = ref}}
    style={styles.flatlist_main}
    data={this.state.items}
    extraData={this.state}
    renderItem={this.renderItem}
    keyExtractor={this.keyExtractor}
    onContentSizeChange={(contentWidth, contentHeight) => {
          flatlistRef.scrollToEnd({animated: true});
    }}
    onLayout={() => {flatlistRef.scrollToEnd({animated: true})}}
/>

onChangedText函数

onFooterTextChanged = (text) => {
    this.setState({
        text: text,
        options_expanded: false,
    });
};

onSendMessage按钮功能

onSendButtonPressed = () => {
    if(this.state.text !== null && this.state.text !== "") {
        this.setState({
            items: [
                ...this.state.items,
                {
                    id: moment().valueOf(),
                    text: this.state.text,
                    date: moment().valueOf(),
                    user: {
                        id: globals.user_id_value,
                        avatar: globals.user_photo,
                    }
                }
            ],
            text: "",
            options_expanded: true,
        });
    }
};

FlatList的renderItem函数

renderItem = (item) => {
    const data = item.item;
    const renderAvatar = this.renderAvatar(item);
    const renderTime = this.renderTime(item);
    if('text' in data){
        return(
            <ChatTextItem
                keyy={data.id}
                self={globals.user_id_value === data.user.id}
                text={data.text}
                user={data.user}
                renderAvatar={renderAvatar}
                sameUser={!renderAvatar}
                renderTime={renderTime}
                time={this.getTime(data.date)}
            />
        )
    } else if('image' in data) {
        return(
            <ChatImageItem
                keyy={data.id}
                self={globals.user_id_value === data.user.id}
                image={data.image}
                renderAvatar={renderAvatar}
                sameUser={!renderAvatar}
                renderTime={renderTime}
                time={this.getTime(data.date)}
            />
        )
    }
};

构造函数,如果有帮助

constructor(props){
    super(props);
    this.state = {
        isLoading: false,
        options_expanded: true,
        text: "",
        image: "",
        items: [],
    };
}

我是用户PureComponent btw。

编辑#1:在TextInput中输入疯子后的控制台 enter image description here 它为我输入的28个字母重新呈现了28次,它确实*已经列出的项目数

编辑#2:对JS文件所做的更改

更改FlatList extraData选项

 <FlatList
      key={'chat'}
      ref={(ref) => {flatlistRef = ref}}
      style={styles.flatlist_main}
      data={this.state.items}
      extraData={this.state.refresh}
      renderItem={this.renderItem}
      keyExtractor={this.keyExtractor}
      onContentSizeChange={(contentWidth, contentHeight) => {
            flatlistRef.scrollToEnd({animated: true});
      }}
      onLayout={() => {flatlistRef.scrollToEnd({animated: true})}}
  />

并更改构造函数以添加刷新状态

 constructor(props){
    super(props);
    this.state = {
        isLoading: false,
        options_expanded: true,
        text: "",
        image: "",
        items: [],
        refresh: false,
    };
}

问题仍然存在

编辑:#3终于找到了问题

作品

<FlatList
                key={'chat'}
                ref={(ref) => {flatlistRef = ref}}
                style={styles.flatlist_main}
                data={this.state.items}
                extraData={this.state.refresh}
                renderItem={this.renderItem}
                keyExtractor={this.keyExtractor}

            />

不起作用

 <FlatList
                key={'chat'}
                ref={(ref) => {flatlistRef = ref}}
                style={styles.flatlist_main}
                data={this.state.items}
                extraData={this.state.refresh}
                renderItem={this.renderItem}
                keyExtractor={this.keyExtractor}
                onContentSizeChange={(contentWidth, contentHeight) => {
                    flatlistRef.scrollToEnd({animated: true});
                }}
                onLayout={() => {flatlistRef.scrollToEnd({animated: true})}}
            />

任何想法为什么?请!

如果有人能帮我找到问题的解决方案,我将不胜感激。

3 个答案:

答案 0 :(得分:0)

由于您的extraData收到了整个州

,这看起来很像
  

这是一个PureComponent,这意味着它不会重新渲染   道具仍然浅薄相等。确保renderItem的所有内容   函数依赖于作为prop(例如extraData)传递而不是   ===更新后,否则您的UI可能无法更新更新。这包括数据支柱和父组件状态

因此,这是预期的行为,因为每次用户在输入字段中输入时都会更新状态。

此外,FlatList应仅呈现(或重新呈现)屏幕中可见的项目

  

为了限制内存并启用平滑滚动,内容是   在屏幕外异步渲染。这意味着可以滚动   比填充率快,并暂时看到空白内容。这是一个   权衡可以调整,以满足每个应用程序的需要,   我们正在努力在幕后改进它。

尝试修复extraData。类似extraData={this.state.refresh}的内容,当用户按下this.state.refresh按钮时会更新send

此处有更多详情:https://facebook.github.io/react-native/docs/flatlist.html

希望有所帮助

答案 1 :(得分:0)

显然,如果我从onLayout中移除onContentSizeChangedFlatList个事件,它会停止渲染任何状态更改,并且只有extraData中提供的状态,仍然无法解决我的问题问题,它只会让业绩出乎意料地变得更糟。 感谢所有帮助解决这个问题的人。

答案 2 :(得分:-1)

我不认为这是错误,这就是我们对你的聊天应用程序所需要的。当您更新每个onPress(onSendButtonPressed)的状态以在列表中显示新消息时。所以它重新呈现列表。可能是我的建议,你只需在你的平面列表中显示最近的消息。即flatList中的最后3或4天消息,当用户超过4天后加载更多消息。这有助于您提高聊天应用程序的性能。