当 SectionList/Flatlist 滚动/渲染项目时 UI 线程似乎被阻塞(React Native)

Posted

技术标签:

【中文标题】当 SectionList/Flatlist 滚动/渲染项目时 UI 线程似乎被阻塞(React Native)【英文标题】:When SectionList/Flatlist is scrolling/rendering items UI thread seems blocked (React Native) 【发布时间】:2019-02-23 13:08:52 【问题描述】:

我们在我们的 react 原生项目中使用 Sectionlist 和 Flatlist,我们使用 websocket 来接收/更新数据。

每次我们通过 websocket 接收数据时,我们都想更新 Sectionlist/Flatlist 中的一些信息,但是我们有超过 100 行,所以当试图重新渲染 UI 线程的列表似乎被阻塞时。因此,onPress 函数延迟了 3~5 秒。

所以我的问题是:

    Flastlist/Sectionlist 是在更新时重新渲染整个列表还是仅重新渲染特定行? (因为我们只更新某些特定行中的一些信息,并不是每一行都有要更新的新信息) 如果它重新渲染整个列表,我怎样才能让 Flastlist 或 Sectionlist 只重新渲染那些特定的行? 如果它只重新渲染特定的行,为什么 UI 似乎仍然被阻塞?我该如何预防这种情况?

    或者问题不在于 UI 块?也许还有其他原因导致 onPress 功能延迟?如果是这样,有什么问题,我该如何解决?

    class RowItem1 extends React.Component
      constructor(props)
      super(props);
     
    
    shouldComponentUpdate = (nextProps, nextState) => 
        if (nextProps.item == this.props.item) 
      return false;
    
     return true;
     ;
    
    render=()=>
     return (
        <View>
            <TouchableWithoutFeedback
                onPress=() =>  consle.log(1234) 
            >
            </TouchableWithoutFeedback>
            <View>
                <Text>this.props.item.text</Text>
                <Text>this.props.item.name</Text>
            </View>
        </View>
    )
     
          
    
    export default class main extends React.Component 
    
             constructor(props) 
            super(props);
        
    
    componentWillMount = () => 
    var ws = new WebSocket('ws://123456');
    ws.onmessage = function (evt) 
        let data = JSON.parse(evt.data);
        this.setState(
            A: data.A,
            B: data.B,
            C: data.C
        );
    ;
    ;
    
    getItemLayout = (data, index) => ( length: 74, offset: 74 * index, index );
    
    renderA = ( item, index, section ) => 
       return <RowItem1 item=item/>      
        
    
    render() 
    return (
        <View>
            <SectionList
                sections=[
                    
                        title: "A",
                        data: this.state.A,
                        renderItem: this.renderA,
                    ,
                    
                        title: "B",
                        data: this.state.B,
                        renderItem: this.renderB,
                    ,
                    
                        title: "C",
                        data: this.state.C,
                        renderItem: this.renderC,
                    
                ]
                initialNumToRender=10
                removeClippedSubviews=true
                getItemLayout=this.getItemLayout
                keyExtractor=(item, index) => item + index
                extraData=this.state
                refreshing=this.state.refreshing
                onRefresh=this.handleRefresh
            />
        </View>
    );
    
            
    

第一次:

    data = A:['text': 0, 'name': 'A','text': 0, 'name': 'B', 'text': 0, 'name':'C']

第二次:

    data = A:['text': 3, 'name': 'A','text': 0, 'name': 'B', 'text': 0, 'name':'C']

比较我收到的两个数据,我只想重新渲染列表的第一行,因为只有第一行数据得到了更新。我该怎么做?

【问题讨论】:

你在做什么来阻止无用的重新渲染,比如你是在使用 pureComponent 还是 shouldComponentUpdate? @HaiderAli 我稍微编辑了我的问题,你介意检查一下吗。非常感谢。我们已经 shouldComponentUpdate 但在重新渲染列表时 onPress 仍然延迟 【参考方案1】:

我知道这真的很晚了,但是对于那些仍然有这个问题的人,你可以通过将 scrollEventThrottle 属性设置为非常高的值来修复它,比如 1000。我应该注意,这真的只有在你不这样做的情况下才有效不需要 onScroll 事件。

<FlatList data=data renderItem=renderItem scrollEventThrottle=1000 />

【讨论】:

scrollEventThrottle * 感谢@Slbox - 已修复

以上是关于当 SectionList/Flatlist 滚动/渲染项目时 UI 线程似乎被阻塞(React Native)的主要内容,如果未能解决你的问题,请参考以下文章

当scrollview快速滚动时如何滚动collectionView?

IOS。当 UIScrollView 滚动时应用另一个滚动动画[关闭]

当用户移动器悬停在滚动条上时如何增加滚动条宽度

当内部元素滚动位置达到顶部/底部时防止父元素滚动?

当焦点文本输入反应本机时,滚动视图无法滚动

如何自动滚动 ScrollViewer - 仅当用户未更改滚动位置时