FlatList中的getItemLayout在第一次渲染时传递索引-1

时间:2019-07-05 12:39:44

标签: react-native react-native-flatlist

我正在使用FlatListinitialScrollIndex实现getItemLayout。但是,每次我的应用启动时,它都会以某种方式呈现第一个元素,然后跳转到实际的initialScrollIndex。这意味着我应该获得的实际性能提升无法正常工作。

在检查getItemLayout函数时,我看到它呈现的第一个索引是-1而不是initialScrollIndex, thus throwing an error and breaking. The other random indexes are passed until initialScrollIndex`。

有什么想法可能会发生这种情况吗?

FlatList:

renderMonthPerMonth() {
const data = this.deriveMonthPerMonthDataFromProps();
const initialScrollIndex = this.deriveInitialScrollIndex();

return (
  <FlatList
    data={data}
    ref={'flatlist'}
    initialNumToRender={3}
    onLayout={this.onLayout} 
    getItemLayout={this.getItemLayout}
    showsVerticalScrollIndicator={false}
    initialScrollIndex={initialScrollIndex}
    renderItem={this.renderOneMonthPerMonth}
    ListHeaderComponent={this.renderListHeader}
    keyExtractor={el => `${el.monthName}-monthPerMonth`}
    onScrollBeginDrag={() => this.onExpandMenu('scroll')}
    ItemSeparatorComponent={this.renderItemSeparator}
    ListFooterComponent={this.renderFooterComponent}
  />
);
}

getItemLayout:

getItemLayout(data, index) {
const monthAsNumber = moment().month(data[index].monthName).format('M')-1;

const SEPARATOR_HEIGHT = 25;
const MONTH_NAME_CONTAINER_HEIGHT = 55;

const ONE_DAY_HEIGHT = (((width-40)/7)/1.1);
const WEEKS_IN_MONTH = this.weeksInMonth(moment().format('YYYY'), monthAsNumber);

// define oneMonthHeight using weeksInMonth method
const oneMonthHeight = (ONE_DAY_HEIGHT * WEEKS_IN_MONTH) + (MONTH_NAME_CONTAINER_HEIGHT + SEPARATOR_HEIGHT);

return {
  length: oneMonthHeight,
  offset: oneMonthHeight * index,
  index,
}
}

控制台:

console screenshot

1 个答案:

答案 0 :(得分:1)

我怀疑问题出在renderItem属性中,随后是renderOneMonthPerMonth()方法中。

参考FlatList docs

  

这是一个PureComponent,表示如果支柱保持浅等,它将不会重新渲染。确保您的renderItem函数依赖的所有内容都作为更新后不是===的道具(例如extraData)传递,否则您的UI可能不会根据更改进行更新。这包括数据属性和父组件状态。

  

renderItem({项目:对象,索引:数字,分隔符:{高亮:函数,取消突出显示:函数,updateProps:函数(选择:字符串,newProps:对象)}))=>?React.Element

拥有this.deriveMonthPerMonthDataFromProps()可能不是纯粹的(取决于那个道具,我看不到)。

  1. 尝试获取所有数据并分配给所传递的renderItem方法外部的const。另外,如果此数据是纯数据且未更改,则可以跳过此步骤。

  2. 接下来的两个可能是问题的症结所在:创建类似于以下内容的渲染函数:

      const renderItem = ({ item, index }) => {
        return <DummyComponent item={item} index={index} /> // item and index are not necessarry just demonstrating
      }
  1. 确保您有一个keyExtractor返回唯一标识符。否则,这将以与您的问题类似的方式出错。请尝试以下操作进行健全性检查
    keyExtractor={(item, index) => index.toString()}

如果上述不是问题,则还需要确保Flatlist上的数据属性是数组,而不是 Object 或其他数据结构,如Flatlist文档的data部分。

如果您的数据属于对象类型,并且您不依靠其他方法来访问键,则可以将初始数据更改为对象数组,如下所示:

[
  { ...monthOneData },
  { ...monthTwoData },
  { ...monthThreeData }
]

或者,如果要将原始数据保留为对象,可以使用

将其转换为键数组。
Object.keys(this.state.data)

然后在FlatList中,您可以执行以下操作:

<FlatList
  data={Object.keys(this.state.data)}
  renderItem={({item}) => 
    <DummyComponent month={this.state.data[item].month} /> // item is now the key value of the objects (almost like a look up table)
    // also not having curly braces implies an implicit return in this case
  }
/>