【问题标题】:Using a FlatList with scrollToEnd使用带有 scrollToEnd 的 FlatList
【发布时间】:2017-11-09 04:20:57
【问题描述】:

我在使用 FlatList 时遇到了两个问题(两者都与 ListView 一起使用)。

我有一个通过每个项目的显示属性显示的列表,然后像这样签入我的 FlatList:

<FlatList
  ref='flatList'
  data={this.state.dataSource}
  enableEmptySections
  renderItem={({item}) => item.display && <Text>{item.text}</Text>} />

当我更改显示属性时,它不会显示。这在 ListView 设置中运行良好。

我的第二个问题是 scrollToEnd 在 scrollToEnd 函数内的“this._listref”上触发了一个未定义的错误。我没有向它传递任何参数。

setTimeout(this.refs.flatList.scrollToEnd, 0)

我的问题是,如何更新列表的数组中的数据,使其在列表中发生变化,第二个问题是如何修复 scrollToEnd 错误?

更新 1:(数据已删除,不再需要)

更新 2: 问题 ONE 已解决,列表需要“extraData”比较以查看是否更新。固定版:

<FlatList
  ref='flatList'
  data={this.state.dataSource}
  extraData={this.state}
  enableEmptySections
  renderItem={({item}) => item.display && <Text>{item.text}</Text>} />

这有点令人费解,但我相信 extraData 可以作为比较来查看该数据集中是否有任何更新。如果是这样,请重新渲染。这个问题就解决了。

“undefined is not an object (evalating 'this._listRef')”仍未修复

更新 3:如果在 setTimeout 函数之外使用,则滚动功能有效

更新 4:

设置初始数据数组

  this.state = {
    dataSource: pageService(state.params.page),
    cursor: 0
  }

设置显示为真:

  renderNextModule() {
    let newCursor = this.state.cursor
    if (newCursor < this.state.dataSource.length-1) {

        newCursor++
        let newSource = this.state.dataSource
        newSource[newCursor].display = true
        this.setState({
            dataSource: newSource,
            cursor: newCursor
        })
    }
  }

【问题讨论】:

  • FlatList 中的浅层是否决定不重新渲染?我将更新我的部分数据
  • 第一个问题解决,更新中
  • 再次更新,这似乎是特定于将其放入包装“setTimeout”函数中

标签: reactjs react-native


【解决方案1】:

对我有用

data={this.state.messages}
ref = "flatList"
onContentSizeChange={()=> this.refs.flatList.scrollToEnd()}

【讨论】:

    【解决方案2】:

    this._listRef 未定义,因为 setTimeout 调用该函数并将其上下文 (this) 设置为 null。

    作为一种解决方法,您实际上可以使用包装函数(这里使用 ES6 语法):

    setTimeout(() => this.refs.flatList.scrollToEnd(), 0)
    

    关于您的第一个问题,我认为您没有以正确的方式解决它。 你是对的,它使用了浅层比较,但你可能不需要 extraData 属性。

    你是在直接改变你的数组吗?您如何更新 item.display 属性?


    对于您的第一个问题,
    替换这一行

    let newSource = this.state.dataSource
    

    由此

    let newSource = this.state.dataSource.slice()
    

    在 JavaScript 中,数组是通过引用复制的,这意味着您不是在克隆数组,而是在改变它;并且由于FlatList 是有效的(这适用于每个PureComponent),当您想要重新渲染它时(通过像您所做的那样设置状态),它会在其新旧道具上进行=== 比较看看有没有变化。

    当您更改旧数组“oldArray === newArray”时,因此决定不再更新。

    这有点简洁和快速,但您可以阅读更多关于为什么需要使用 .slice() here 创建新数组的信息。这适用于 JavaScript 中的数组和对象。

    【讨论】:

    • 数组是一个状态值,所以我用setState来改变它。初始值是从另一个函数“pageData(pageNumber)”中提取的,并返回。我也通过 setState 更新 item.display 属性。我会用代码更新
    • 我忘记绑定我的 scrollToBottom...这解决了这个问题 this.scrollToBottom = this.scrollToBottom.bind(this) 仍然有兴趣了解如何重新渲染该区域(如果您在上述解决方案中发现问题)
    • 添加了解决方案和解释:)
    • (你现在可以移除 extraData 属性了)
    • 谢谢,我会测试一下!我认为 react 做了一些魔术并返回了值,而不是传递引用
    【解决方案3】:

    在功能组件的情况下。

    let flatList = React.useRef(null);
    

    在你的 FlatList 组件中

    <FlatList
      ref={flatList}
      onContentSizeChange={()=> flatList.current.scrollToEnd()}
      ....
     />
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多