Повторный рендеринг FlatList каждый раз, когда я набираю текст в TextInput

Guy спросил: 28 апреля 2018 в 09:46 в: javascript

Я не думаю, что это ошибка, больше похоже на то, что я делаю что-то не так, но вот оно. Я создаю компонент чата для своего приложения, это очень просто, я печатаю что-то нажатие кнопки отправки добавляет к список и показы. Десять лет назад я обнаружил, что если бы я начал набирать большие и быстрые сообщения, мой JS FPS упал бы до 10, 5 даже 1, и я узнал сегодня благодаря внедрению отображения данных / времени для сообщений, которые каждый раз, когда я печатаю что-то в TextInput и запустить событиеChangeText и изменить состояние "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,
    });
};

Функция кнопки отправки_ссылки

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,
        });
    }
};

renderItem Функция для FlatList

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 Это повторно - 28 раз за 28 букв, которые я набрал, и он делает это количество элементов в списке уже

Изменить # 2: Изменения, внесенные в файл JS

Изменены дополнительные данные FlatList option

 <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 ответа

soutot ответил: 28 апреля 2018 в 11:10

Похоже, что ваш extraData получает все состояние

Это PureComponent, что означает, что он не будет повторно рендерить ifprops, оставаясь неглубоко. Убедитесь, что все, на что зависит ваша функция renderItem, передается как поддержка (например, extraData), которая не является === после обновлений, в противном случае ваш пользовательский интерфейс может не обновляться при изменениях. Это включает в себя данные и состояние родительского компонента.

Итак, это ожидаемое поведение, так как вы обновляете свое состояние каждый раз, когда пользователь вводит ваше поле ввода.

, FlatList должен отображать (или воспроизводить) только элементы, видимые на экране

Чтобы ограничить память и обеспечить плавную прокрутку, контент передается асинхронно за кадром. Это означает, что можно прокручивать пробел, чем скорость заполнения, и на мгновение видеть пустой контент. Это atradeoff, который можно настроить в соответствии с потребностями каждого приложения, и мы работаем над его улучшением за кулисами.

Попробуйте исправить ваш extraData. Что-то вроде extraData={this.state.refresh}, где this.state.refresh обновляется, когда пользователь нажимает кнопку send.

Подробнее здесь: https://facebook.github .io / react-native / docs / flatlist.html

Надеюсь, что это поможет

Guy ответил: 28 апреля 2018 в 11:21
Спасибо за ответ, я сменил Flatlist на extraData={this.state.refresh} и в конструкторе refresh: false и никогда не менял его, но он остается повторно визуализировать каждый раз, когда я набираю и отлаживаю его, дает мне изображение, которое я опубликовал выше в редакторе №1.
soutot ответил: 28 апреля 2018 в 11:48
У вас есть методы рендеринга внутри вашего renderItem. Любой из них потребляет ваше государство? Btw, theres опечатка на key подсказке компонента текстового элемента yout chat
Guy ответил: 28 апреля 2018 в 11:52
Во-первых, чтобы ответить на ваш вопрос, я не использую setState в любом из элементов, а во-вторых, я предоставил свой extraData Prop с помощью this.state.refresh и работал на / android папка gradlew cleanBuildCache , но по какой-то причине extraData Prop сохраняет grabbing this.state, а не this.state.refresh Любые идеи? Заранее спасибо.
Guy ответил: 28 апреля 2018 в 12:00
Я выяснил, что вызывает его, по-видимому, если я удалю onContentSizeChanged и onLayout, он останавливает повторный рендеринг при вводе, почему?
Guy ответил: 28 апреля 2018 в 12:20

По-видимому, если я удаляю onLayout и onContentSizeChanged события из моего FlatList, он останавливает рендеринг при любых изменениях состояния и только состояние, предоставленное в extraData, "Решите мою проблему, и это только сделало производительность хуже удивительно. Спасибо всем, кто помог решить эту проблему.

Jeeva ответил: 28 апреля 2018 в 10:04

Я не думаю, что это ошибка. Это то, что нам нужно для вашего приложения для чата. Когда вы обновляли состояние для каждого onPress (onSendButtonPressed), чтобы показать новое сообщение в списке. Таким образом, он повторно отображает список. Может быть, я предлагаю, вы просто показываете последние сообщения в своем списке. т.е. последнее сообщение 3 или 4 дня в плоском списке и загружать больше, когда пользователь возвращается за 4 дня. Это поможет вам улучшить производительность вашего приложения чата.

Guy ответил: 28 апреля 2018 в 10:07
Я имею в виду, что мой FlatList повторно рендерит каждый раз, когда я печатаю что-то в TextInput, если проблема была только повторной рендерингом, когда я нажимаю send, это будет хорошо, но каждый раз перерисовывается каждый раз и запускается onTextChanged для обновления "Text", государственный