首页 文章

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

提问于
浏览
-1

我不认为这是一个错误,更像是我做错了什么但是它就这样了 . 我正在为我的应用程序构建一个聊天组件,它非常简单,我输入了一些按下发送按钮添加到列表和显示 . 几天前,我发现,如果我开始输入大而快的消息,我的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终于找到了问题

Works

<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}

            />

Doesn't Work

<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 回答

  • -1

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

  • 0

    显然,如果我从 FlatList 删除了 onLayoutonContentSizeChanged 事件,它会停止渲染任何状态更改,只有extraData中提供的状态,仍然无法解决我的问题,只会让性能更糟糕 . 感谢所有帮助解决这个问题的人 .

  • 0

    看起来这是因为你的 extraData 收到整个州

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

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

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

    为了限制内存并启用平滑滚动,内容将在屏幕外异步呈现 . 这意味着可以比填充率更快地滚动并暂时看到空白内容 . 这是一个可以调整以适应每个应用程序需求的权衡,我们正在努力在幕后进行改进 .

    尝试修复 extraData . 像 extraData={this.state.refresh} 之类的东西,当用户按下 send 按钮时 this.state.refresh 会被更新 .

    更多细节:https://facebook.github.io/react-native/docs/flatlist.html

    希望能帮助到你

相关问题