100

与 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} />
4

20 回答 20

208

使用extraDataFlatList 组件上的属性。

正如文档所述:

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

于 2017-06-16T23:21:06.013 回答
65

如需快速简单的解决方案,请尝试:

  1. 将额外数据设置为布尔值。

    extraData={this.state.refresh}

  2. 当您想要重新渲染/刷新列表时切换布尔状态的值

    this.setState({ 
        refresh: !this.state.refresh
    })
    
于 2018-03-27T06:37:35.203 回答
22

哦,这很简单,只需使用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将更新,因为不可变对象将与之前的对象不同。

于 2017-09-01T17:57:25.613 回答
8

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

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

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

于 2018-09-09T13:29:14.037 回答
4

如果您要拥有一个 Button,您可以使用 onPress 中的 setState 更新数据。然后 SetState 将重新渲染您的 FlatList。

于 2017-04-13T17:30:57.740 回答
4

经过大量搜索和寻找真正的答案,我终于得到了我认为最好的答案:

       <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} 在我改成这个之后它就像魅力一样工作我希望这对某人有所帮助。

于 2019-01-27T18:14:02.590 回答
3

只是对此处先前答案的扩展。要确保的两个部分,请确保您添加了 extraData 并且您的 keyExtractor 是唯一的。如果您的 keyExtractor 是常量,则不会触发重新渲染。

<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
                                    </FlatList>
于 2020-02-11T01:09:17.543 回答
1

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

const [selected, setSelected] = useState(machine)

useEffect(() => {
    setSelected(machine)
}, [machine])
于 2019-08-09T01:57:12.017 回答
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>
    );
  }
于 2018-12-06T07:49:57.303 回答
0
const [itemSelected, setItemSelected] = setState(null);
....
const FlatListItem = (item) => {
    return (
        <TouchableOpacity onPress={() => setItemSelected(item.id)}>
            <View style={ (itemSelected === item.id) ? style.itemWrapperActive : style.itemWrapper }>
                <Text>{ item.label }</Text>
            </View>
        </TouchableOpacity>
    )
}
....
<FlatList
    ItemSeparatorComponent={() => <View style={{ width: 20 }} />}
    data={ flatListData }
    renderItem={ ({item}) => FlatListItem(item) }
    keyExtractor={ (item) => item.id }
    extraData={ itemSelected }
/>
于 2021-05-08T23:30:10.803 回答
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,
}]
于 2018-03-02T14:36:45.880 回答
0

我正在使用功能组件,因为我正在使用带有 redux 数据的 Flatlist。我正在使用 Redux 商店管理所有状态。这是在 api 调用后更新 Flatlist 数据的解决方案。

我最初是这样做的:-

const DATA  = useSelector((state) => state.address.address);


<FlatList
    style = {styles.myAddressList}
    data = {DATA}
    renderItem = {renderItem}
    keyExtractor = {item => item._id}
    ListEmptyComponent = {EmptyList}
    ItemSeparatorComponent={SeparatorWhite}
    extraData = {refresh}
    
    />

但数据根本没有重新渲染我的 Flatlist 数据。

作为一个解决方案,我确实喜欢下面给出的: -

<FlatList
    style = {styles.myAddressList}
    data = {useSelector((state) => state.address.address)}
    renderItem = {renderItem}
    keyExtractor = {item => item._id}
    ListEmptyComponent = {EmptyList}
    ItemSeparatorComponent={SeparatorWhite}
    />

我将 Redux 状态直接传递给 Flatlist 数据源,而不是将其分配给变量。

谢谢你。

于 2021-01-27T08:16:45.623 回答
0

对我来说,诀窍是 extraData 并再次深入到 item 组件中

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 });
    }
  }
}
于 2018-06-13T12:04:49.730 回答
0

如果我们想让 FlatList知道数据同时改变了 prop 和 state,我们可以构造一个同时引用 prop 和 state 的对象并刷新 flatlist。

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

文档:https ://facebook.github.io/react-native/docs/flatlist#extradata

于 2018-12-19T11:00:16.460 回答
0

将您的交互更改的变量放在extraData

你可以有创意。

例如,如果您正在处理带有复选框的更改列表。

<FlatList
      data={this.state.data.items}
      extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
      renderItem={({item}) => <View>  
于 2018-08-28T07:54:12.457 回答
0

像下面这样做会立即使平面列表项的更改立即反映出来。如果您不使用 redux,您也可以在组件中类似地执行此操作。

  let list = Object.assign([], state.auctionList);
  let objIndex;
  //Find index of specific object using findIndex method.
  objIndex = list.findIndex(
    obj => obj.auction_vehicles.vehicle_id == payload.vehicle_id,
  );

  // //Update object's property.
  list[objIndex].auction_vehicles.time_left = payload.offer_expiry_time;
  list[objIndex].auction_vehicles.starting_price = payload.amount;
  list[objIndex].auction_vehicles.bidding_status =
    payload.highest_bidder_flag;

  return { ...state, auctionList: list };
于 2021-12-28T07:11:10.347 回答
0

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

 <FlatList
          data={data }
          style={FlatListstyles}
          extraData={this.state}
          renderItem={this._renderItem}
       />
于 2019-06-22T03:52:57.280 回答
0

对于那些使用 redux 的人,我使用extraData了 prop 并在那里添加了加载,我还创建了一个名为usePrevious

import {useEffect, useRef} from 'react';

export const usePrevious = <T>(value: T): T | undefined => {
  const ref = useRef<T>();
  useEffect(() => {
    ref.current = value;
  });
  return ref.current;
};

并像这样在我的项目上使用它。

const prevData = usePrevious({data});

//CODES...

useEffect(() => {
    if (prevData?.data === undefined) {
      return;
    }
    if (prevData?.data?.someID !== data?.someId) {
      // do something.
      showSubChildren(false)
    }
  }, [data?.AuctionName, prevData, resetItemStates]);

所以这里基本上发生的是,您的项目将检查数据是否来自undefined(第一次)。然后它将检查某些数据属性是否已更改,如果已更改,您应该做一些事情。

于 2021-08-27T02:10:24.943 回答
-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

于 2019-11-14T01:03:51.580 回答
-1

只需使用:

onRefresh={true}

在你的flatList组件里面。

于 2019-02-13T07:14:06.307 回答