Як повторно відтворити плоский список?


86

На відміну від ListView, ми можемо оновити this.state.datasource. Чи існує якийсь метод або приклад для оновлення FlatList або його повторного відтворення?

Моя мета - оновити текстове значення, коли користувач натискає кнопку ...

renderEntries({ item, index }) {
    return(
        <TouchableHighlight onPress={()=> this.setState({value: this.state.data[index].value+1})>
             <Text>{this.state.data[index].value}</Text>
        </TouchableHighlight>
    )
}

<FlatList 
    ref={(ref) => { this.list = ref; }} 
    keyExtractor={(item) => item.entry.entryId} 
    data={this.state.data} 
    renderItem={this.renderEntries.bind(this)} 
    horizontal={false} />

7
У документах для FlatList сказати : «Це PureComponentозначає , що він не буде знову зробити , якщо реквізит залишається мілководним дорівнює. Переконайтеся , що всі ваші renderItemфункції залежать від того, передаються в якості опори, що не ===після поновлення, в іншому випадку інтерфейс не може оновлювати щодо змін. Це включає dataпроп і батьківський компонент. " Ви дотримуєтесь цієї поради?
Йорданія, біг

3
Незалежно від того, з чим я намагався, extraDataі shouldItemUpdateя не міг отримати список для повторного відтворення. У підсумку я зробив очищення штату, чекав, поки це зробить, а потім оновив штат. this.setState({ data: null }, () => { this.setState({ data: actualData }) });
Джошуа Пінтер

Відповіді:


186

Використовуйте extraDataвластивість компонента FlatList.

Як зазначено в документації:

Переходячи extraData={this.state}до, FlatListми переконуємось FlatList, що відтвориться, коли state.selectedзміни. Без встановлення цього реквізиту, FlatListвін не знав би, що йому потрібно повторно відтворювати будь-які елементи, оскільки це також є, PureComponentі порівняння реквізиту не покаже жодних змін.


34
Я використовую redux і в такому випадку надсилаю дані, як data={this.props.searchBookResults}і ні, extraData={this.state}ні extraData={this.props}для мене не працюю. І data={this.props.searchBookResults}теж не працює. Що робити ?
Суджіт

8
Використовуйте extraData: для оновлення вашого <FlatList>... data={this.props.searchBookResults} extraData={this.state.refresh} onPress={()={this.setState({ refresh: !refresh})}
Nay

9
Я борюся з тією ж проблемою. Не має значення, що я передаю extraData, компонент не оновлюється :(
Денис Каппеліні,

2
@DenisCappelini, переконайтеся, що дані, що передаються в extraDataреквізит, змінюються, коли дочірні елементи потрібно повторно відтворювати. Наприклад, якщо елементи списку можуть бути активними / неактивними, переконайтесь, що змінна стану незалежно від того, чи є частина this.stateоб’єкта чи this.propsоб’єкт тим, що має входити всередину extraData. Це може бути курсор, масив активних елементів тощо
Emperor_Earth

1
@Sujit Я стикався з тією ж проблемою, але потім зрозумів, що реалізував shouldComponentUpdate(), як тільки я оновив це або повністю прокоментував, справи працювали так, як це описано в документації.
JanithaR

51

Для швидкого та простого рішення Спробуйте:

  1. встановити додаткові дані на логічне значення.

    extraData = {this.state.refresh}

  2. Переключіть значення логічного стану, коли потрібно повторно відтворити / оновити список

    this.setState({ 
        refresh: !this.state.refresh
    })
    

Це якраз те, що мені потрібно, оскільки я буду додавати дані до опису даних. Крім того, це надзвичайно дивна реалізація командою React-Native ... більше сенсу було б мати функцію оновлення або властивість даних. IE: this.data.refresh(). Натомість ми встановлюємо логічне значення та змінюємо його. Булеве значення саме по собі не має значення, тож який сенс у ньому існувати? ... (Немає жодного сенсу, крім того, щоб оновити дані, чи не так?)
YungGun

@HradeshKumar Я роблю це, але останній елемент всередині даних він не може зникнути!
DevAS

це працює як чарівність, але я все ще не знаю, чому this.state.usersце не спрацювало, хоча я міняв прапор у деяких користувачів.
shyammakwana.me

21

О, це просто, просто використовуй extraData

Ви бачите, як додаткові дані працюють за лаштунками, це FlatList або VirtualisedList просто перевіряє , чи змінився об'єкт звичайним onComponentWillReceivePropsметодом.

Отже, все, що вам потрібно зробити, це переконатися, що ви надаєте щось, що змінюється на extraData.

Ось що я роблю:

Я використовую immutable.js, тому все, що я роблю, це передавати мапу (незмінний об’єкт), що містить все, що я хочу дивитись.

<FlatList
    data={this.state.calendarMonths}
    extraData={Map({
        foo: this.props.foo,
        bar: this.props.bar
    })}
    renderItem={({ item })=>((
        <CustomComponentRow
            item={item}
            foo={this.props.foo}
            bar={this.props.bar}
        />
    ))}
/>

Таким чином, коли this.props.fooабо this.props.barзміниться, ми CustomComponentRowоновимось, оскільки незмінний об'єкт буде іншим, ніж попередній.


2
я нарешті зрозумів extraData! дякую за посилання на VirtualisedListкод!
Tushar Koul,

привіт, @ SudoPiz Я хочу повторно відтворити Flatlist після видалення останнього елемента, можу перевірити це Q stackoverflow.com/questions/58780167/…
Олівер Д,

6

Добре. Я щойно дізнався, що якщо ми хочемо, щоб FlatList знав, як змінюються дані за межами опису даних, нам потрібно встановити його в extraData, тому я роблю це так:

<FlatList data={...} extraData={this.state} .../>

зверніться до: https://facebook.github.io/react-native/docs/flatlist#extradata


1
Найкраща реалізація ... Я вважав за краще встановити її такою ж, як і пропс даних, тому вона не оновлюється, коли щось у штаті змінюється, але це НАЙБІЛЬШЕ реалізація. Дякую!
Роберт

привіт, @MahdiBashirpour Я хочу повторно відобразити Flatlist після видалення останнього елемента, можу перевірити цей Q stackoverflow.com/questions/58780167/…
Олівер Д

4

Якщо ви збираєтеся мати кнопку, ви можете оновити дані за допомогою setState всередині onPress. Потім SetState повторно відтворить ваш FlatList.


2
у моєму дотичному світлі є setState. setState працює нормально, але список не відображає оновлення значення стану -> this.state.value
shalonteoh

Значення у вашому FlastList не оновлюються, оскільки ви не оновлюєте джерело даних безпосередньо. this.state.data - це те, що відображається за допомогою FlatList, але в onPress ви лише оновлюєте this.state.value.
WilliamC

вибачте за мою помилку, друкарська помилка. повинно бути this.state.data [index] .value
shalonteoh

3

після багатьох пошуків та пошуку реальної відповіді нарешті я отримав відповідь, яка, на мою думку, є найкращою:

       <FlatList
      data={this.state.data}
      renderItem={this.renderItem}
      ListHeaderComponent={this.renderHeader}
      ListFooterComponent={this.renderFooter}
      ItemSeparatorComponent={this.renderSeparator}
      refreshing={this.state.refreshing}
      onRefresh={this.handleRefresh}
      onEndReached={this.handleLoadMore}
      onEndReachedThreshold={1}
      extraData={this.state.data}
      removeClippedSubviews={true}
      **keyExtractor={ (item, index) => index }**
              />
    .....

моєю основною проблемою було (KeyExtractor), я не використовував його таким чином. не працює: keyExtractor = {(item) => item.ID} після того, як я змінився на це, він працював як шарм, сподіваюся, це комусь допоможе.


Ви можете вказати значення this.state.refreshingі функцію handleRefresh?
DevAS

1

Я вирішив цю проблему, додавши, extraData={this.state}будь ласка, перевірте код нижче, щоб отримати докладнішу інформацію

render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={this.state.arr}
          extraData={this.state}
          renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
        />
      </View>
    );
  }

1

Просто продовження попередніх відповідей тут. Дві частини, щоб переконатися, що ви додали додаткові дані та що ваш keyExtractor унікальний. Якщо ваш keyExtractor постійний, рендерінг не буде ініційований.

<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
                                    </FlatList>

0

Я замінив FlatListна, SectionListі це належним чином оновлюється при зміні стану.

<SectionList
  keyExtractor={(item) => item.entry.entryId} 
  sections={section}
  renderItem={this.renderEntries.bind(this)}
  renderSectionHeader={() => null}
/>

Єдине, що потрібно мати на увазі, це те, що sectionмає різну структуру:

const section = [{
  id: 0,
  data: this.state.data,
}]

0

Для мене фокусом стали extraData і деталізація компонента елемента ще раз

state = {
  uniqueValue: 0
}

<FlatList
  keyExtractor={(item, index) => item + index}
  data={this.props.photos}
  renderItem={this.renderItem}
  ItemSeparatorComponent={this.renderSeparator}
/>

renderItem = (item) => {
  if(item.item.selected) {
    return ( <Button onPress={this.itemPressed.bind(this, item)}>Selected</Button> );
  }
  return ( <Button onPress={this.itemPressed.bind(this, item)}>Not selected</Button>);
}

itemPressed (item) {
  this.props.photos.map((img, i) => {
    if(i === item.index) {
      if(img['selected') {
        delete img.selected;
      } else {
        img['selected'] = true;
      }
      this.setState({ uniqueValue: this.state.uniqueValue +1 });
    }
  }
}

0

Помістіть змінні, які будуть змінені вашою взаємодією на extraData

Ви можете бути креативними.

Наприклад, якщо ви маєте справу зі змінним списком із позначками на них.

<FlatList
      data={this.state.data.items}
      extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
      renderItem={({item}) => <View>  

0

Якщо ми хочемо, щоб FlatList знав, як дані змінюються як prop, так і стан , ми можемо побудувати об’єкт, що посилається як на prop, так і на стан, і оновити список плоским.

const hasPropOrStateChange = { propKeyToWatch: this.props, ...this.state};
<FlatList data={...} extraData={this.hasPropOrStateChange} .../>

Документи: https://facebook.github.io/react-native/docs/flatlist#extradata


0

У списку response-native-flat вони є властивістю, що називається extraData. додайте рядок нижче до вашого списку квартир.

 <FlatList
          data={data }
          style={FlatListstyles}
          extraData={this.state}
          renderItem={this._renderItem}
       />

0

У цьому прикладі, щоб змусити повторно відтворити, просто змініть змінну machine

const [selected, setSelected] = useState(machine)

useEffect(() => {
    setSelected(machine)
}, [machine])

-1

Просто використовуйте:

onRefresh={true}

всередині вашого flatListкомпонента.


1
це створює помилку, тоді вам потрібно використовувати refreshingprop
mahmoudafer

-1

ExtraData Flatlist не працював для мене, і я випадково використовував проп від redux. Це звучало подібно до питань із коментарів у відповіді ED209. Я в кінцевому підсумку зателефонував setState, коли отримую підставку.

componentWillReceiveProps(nextProps: StateProps) {
    if (this.props.yourProp != null && nextProps.yourProp) {
        this.setState({ yourState: processProp(nextProps.yourProp) });
    }
}


<FlatList
  data={this.state.yourState}
  extraData={this.state.yourState}
/>

Для тих, хто використовує> React 17, використовуйте getDerivedStateFromProps

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.