如何重新呈现单位列表?


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文档说:“这是a PureComponent,这意味着如果props保持浅浅相等,它将不会重新渲染。请确保renderItem函数所依赖的所有内容都作为非===更新后的prop传递,否则您的UI可能不会更新更改。包括dataprop和父组件状态。” 您是否遵循此建议?
乔丹(Jordan)

3
不管我尝试了什么extraDatashouldItemUpdate,都无法重新渲染列表。我最终要做的是清除状态,等待状态渲染,然后更新状态。this.setState({ data: null }, () => { this.setState({ data: actualData }) });
Joshua Pinter

Answers:


186

使用extraDataFlatList组件上的属性。

如文档所述:

通过传递extraData={this.state}FlatList我们,确保更改FlatList时将重新呈现自己state.selected。如果不设置此道具,FlatList就不会知道它需要重新渲染任何项目,因为它也是a PureComponent,并且道具比较不会显示任何更改。


34
我正在使用redux,在这种情况下,发送数据的方式类似,data={this.props.searchBookResults}而这两种方式extraData={this.state}都不extraData={this.props}适合我。而且data={this.props.searchBookResults}也不起作用。该怎么办 ?
Sujit

8
而额外用途:刷新<FlatList>... data={this.props.searchBookResults} extraData={this.state.refresh} onPress={()={this.setState({ refresh: !refresh})}
不然

9
我在同一个问题上挣扎。不管我继续传递什么extraData,组件都不会更新:(
Denis Cappelini

2
@DenisCappelini,请确保extraData在必须重新呈现子项时,传递到prop的数据会更改。例如,如果列表项可以是活动的/不活动的,请确保状态变量(无论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我做到了,但是Data里面的最后一项不能消失!
DevAS

这就像魅力一样起作用,但是this.state.users即使我在某些用户中更改了标志,我仍然不知道为什么为什么不起作用。
shyammakwana.me

21

哦,这很简单,只需使用 extraData

您会看到多余的数据在后台工作的方式是FlatListVirtualizedList,它只是通过常规方法检查对象是否已更改onComponentWillReceiveProps

因此,您所要做的就是确保您提供了一些可以更改的内容extraData

这是我的工作:

我正在使用immutable.js,所以我要做的就是传递包含我要观看的内容的Map(不可变对象)。

<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.foothis.props.bar更改时,我们CustomComponentRow将进行更新,因为不可变对象将与之前的对象不同。


2
我终于明白了extraData!感谢您的VirtualisedList代码链接!
Tushar

你好,@ SudoPiz我想删除最后一个项目之后重新渲染Flatlist,可以检查这个问答stackoverflow.com/questions/58780167/...
奥利弗d

6

好的,我刚刚发现,如果我们想让FlatList知道数据道具之外的数据变化,我们需要将其设置为extraData,所以我现在这样:

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

参考:https : //facebook.github.io/react-native/docs/flatlist#extradata


1
最好的实现...我更喜欢将其设置为与数据道具相同,因此当状态发生任何变化时它都不会刷新,但这到目前为止是最简单的实现。谢谢!
罗伯特·基欧

你好,@MahdiBashirpour我想删除最后一个项目之后重新呈现Flatlist,可以检查这个问答stackoverflow.com/questions/58780167/...
奥利弗d

4

如果要有一个Button,则可以在onPress内使用setState更新数据。然后SetState将重新呈现您的FlatList。


2
在我的touchable亮点中有一个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

这里只是先前答案的扩展。确保两部分,确保您添加了extraData并且keyExtractor是唯一的。如果您的keyExtractor不变,则不会触发重新渲染。

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

0

我已替换为FlatListSectionList并且状态更改已正确更新。

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

唯一需要记住的是section具有diff结构:

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

在react-native-flatlist中,它们是称为extraData的属性。将以下行添加到您的单位列表中。

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

0

在此示例中,要强制重新渲染,只需更改变量 machine

const [selected, setSelected] = useState(machine)

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


-1

Flatlist的extraData对我不起作用,我碰巧正在使用来自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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.