bolan9999 / react-native-largelist

The best large list component for React Native.
https://bolan9999.github.io/react-native-largelist/
MIT License
2.32k stars 261 forks source link

Large list and water fall both slow to update items #452

Open AftabUfaq opened 3 years ago

AftabUfaq commented 3 years ago

1: Dev Operating System window 10

2: Target OS android 11 inifnix note 10, redemi note 8 android 10, samsumg A51 android 11, samsung j2 android 8 3: real device

4: package.json

 "react-native": "0.64.2",
 "react-native-spring-scrollview": "^3.0.1-rc.5",
 "react-native-largelist-v3": "^3.1.0-rc.1",

5.

DocumentScreen.js

import React, {useEffect, useState} from 'react'
import {SafeAreaView,View, StyleSheet, Platform} from 'react-native'
import {WaterfallList } from 'react-native-largelist-v3'
import {useSelector, useDispatch} from 'react-redux';
import Item from '../components/DocumentItem'
import { BUTTONRADIUS, COLORS, FONTS } from '../constants';
const DocumentScreen = () => {
    const {allconverteddocuments} = useSelector(state => state.ConvertedDocumentsReducer)
    const [data, setData] = useState([])

    useEffect(() => {
        getfiledetails(allconverteddocuments).then((data) => {
            setData(data)
        })
    },[])

    const renderItem = (item, index) => (
        <Item item={item} />
    )

    return(
    <View style={styles.mainView}>

        <SafeAreaView>
            <WaterfallList 
                data={data}
                bounces={false}
                numColumns={1}
                renderItem={renderItem}
                heightForItem={() => 70}
            />
        </SafeAreaView>
    </View>
    )
}

export default DocumentScreen;

const styles = StyleSheet.create({
    mainView: {
        backgroundColor:"#ffffff",
        flexGrow:1
    },
    RowView:{
        backgroundColor:"#eee",
        paddingVertical:5,
        marginHorizontal:5, 
        alignItems:"center", 
        paddingHorizontal:20 , 
        marginVertical:5,
        borderRadius:BUTTONRADIUS.medium,
        elevation: 4,
    },
    nameText:{
        color:COLORS.lightblack,
        fontFamily:FONTS.medium
    },
    typeText:{
        color:COLORS.gray,
        fontSize:12,
        fontFamily:FONTS.regular
    }
})

DocumentItem.js

import React, {useState,memo, useCallback} from 'react'
import {Text, StyleSheet, TouchableOpacity,  } from 'react-native'
import { Col, Row, Grid } from "react-native-easy-grid";
import Share from 'react-native-share';
import WORDICON from '../assets/ppticon.svg'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import {getfilesize, getdate} from '../services'
import { BUTTONRADIUS, COLORS, FONTS, SCREENS, width } from '../constants';
import * as RootNavigation from '../navigations/Rootnavigator'
import Dialog from "react-native-dialog";
import Menu, {
    MenuProvider,
    MenuOptions,
    MenuOption,
    MenuTrigger,
  } from 'react-native-popup-menu';
const Item = ({ item }) => {
    const [state, setState] = useState(false)
    const [isModalVisible, setModalVisible] = useState(false);
    const [deleteModal, setDeleteModal] = useState(false)
    const [rename , setRename] = useState("")

    const onOptionSelect = (value) => {
        if(value == "openfile"){
            openFile();
        }else if(value == "sharefile"){
            ShareFile()
        }else if(value == "rename"){
            RenameFile()
        }else if(value == "delete"){
            DeleteFileFunction()
        }
        setState(false);
    }

    const openFile = () => {
        RootNavigation.navigate(SCREENS.VIEWPDFSCREEN, {path:item.path})
    }

    const ShareFile = useCallback(function () {
        Share.open({
            url: `file://${item.path}`,
            type: 'application/pdf',
        }).then((result) => {
            console.log(result)
        }).catch((err) =>{

            if(err.message == "User did not share"){

            }else{
                alert('Some Error Occured please try again');
            }
        });
    }, []); 

    const RenameFile = () => {
        setModalVisible(true)
    }

    const onTriggerPress = () => {
        setState(true);
    }

    const  onBackdropPress = () =>  {
        setState(false);
    }

    const RenameFileFunction = () => {
        setModalVisible(false)
    }

    const DeleteFileFunction = () => {
        setDeleteModal(!deleteModal)
    }

    return (
        <Grid>
            <Row style={styles.RowView}>
                <Col size={1}>
                    <WORDICON width={40} height={40} />
                </Col>
                <Col size={4.5} style={{paddingVertical:10,}}>
                    <Row style={{justifyContent:"space-between", width:width}}>
                        <Col size={10}>
                            <Text numberOfLines={1} style={styles.nameText} >{item.filename}</Text>
                        </Col>

                    </Row>

                    <Row>    
                        <Col size={1}>
                            <Text style={styles.typeText} >{getfilesize(item.size)}</Text>
                        </Col>
                        <Col size={2}>
                            <Text style={styles.typeText}>{getdate(item.lastModified)}</Text>
                        </Col>                    
                    </Row>
                </Col>
                <Col size={.7} style={{justifyContent:"center", alignItems:"flex-end"}}>
                    <Menu
                        opened={state}
                        onBackdropPress={() => onBackdropPress()}
                        onSelect={value => onOptionSelect(value)}>
                        <MenuTrigger >
                            <TouchableOpacity onPress={() => onTriggerPress()}>
                                <MaterialCommunityIcons name={"dots-vertical"} size={26} />
                            </TouchableOpacity>
                        </MenuTrigger>
                        <MenuOptions 
                            style={styles.menuView} 
                            optionsContainerStyle={styles.menuView}>

                            <MenuOption value={"openfile"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"file-pdf"} size={16} color={COLORS.lightblack}/>
                                <Text style={{...styles.menuText, marginLeft:5,}}>Open File</Text>
                            </MenuOption>
                            <MenuOption value={"sharefile"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"share-variant"} size={16} color={COLORS.lightblack}/>
                                <Text style={{...styles.menuText, marginLeft:5,}}>Share File</Text>
                            </MenuOption>
                            <MenuOption value={"rename"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"rename-box"} size={16} color={COLORS.lightblack}/>
                                <Text style={{...styles.menuText, marginLeft:5,}}>Rename</Text>
                            </MenuOption>
                            <MenuOption value={"delete"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"delete"} size={16} color={COLORS.danger}/>
                                <Text style={{...styles.menuText,color:COLORS.danger, marginLeft:5,}}>Delete</Text>
                            </MenuOption>

                        </MenuOptions>
                   </Menu>
                </Col>
            </Row>
            <Dialog.Container visible={isModalVisible}>
                <Dialog.Title>Rename File</Dialog.Title>
                <Dialog.Description>
                    Please Enter File Name
                </Dialog.Description>
                <Dialog.Input 
                    value={rename}
                    onChangeText={(text) => setRename(text)}
                />
                <Dialog.Button label="Cancel" style={{color:"red"}} onPress={() => setModalVisible(false)} />
                <Dialog.Button label="OK" onPress={() => RenameFileFunction()} />
            </Dialog.Container>

            <Dialog.Container visible={deleteModal}>
                <Dialog.Title>Delete File</Dialog.Title>
                <Dialog.Description>
                    Are Your Sure 
                </Dialog.Description>
                <Dialog.Button label="Cancel" onPress={() => setDeleteModal(false)} />
                <Dialog.Button label="OK" style={{color:"red"}}  onPress={() => DeleteFileFunction()} />
            </Dialog.Container>
        </Grid>

    )}
export default memo(Item) ;

const styles = StyleSheet.create({
    mainView: {
        backgroundColor:"#ffffff",
        flexGrow:1
    },
    RowView:{
        backgroundColor:"#eee",

        marginHorizontal:5, 
        alignItems:"center", 
        paddingHorizontal:10 , 
        marginVertical:5,
        borderRadius:BUTTONRADIUS.medium,
        elevation: 4,
    },
    nameText:{
        color:COLORS.lightblack,
        fontFamily:FONTS.medium
    },
    typeText:{
        color:COLORS.gray,
        fontSize:12,
        fontFamily:FONTS.regular
    },
    menuText:{
        color:COLORS.lightblack,
        fontSize:12,
        fontFamily:FONTS.regular
    },
    menuView:{
        backgroundColor:"#fff", 
        maxWidth:100, 
        borderRadius:10
    },
    menuOptionsStyle:{
        paddingHorizontal:10, 
        paddingVertical:5,
        borderBottomWidth:0,
        flexDirection:"row",

    }
})

tried this with memo and without memo but same result

Here is a sample video

https://user-images.githubusercontent.com/34965107/129177152-cfb498f0-1e22-49cd-a941-1e58577ff466.mp4

bolan9999 commented 2 years ago

It seems that your item is too complicated. LargeList is reused component to resolve black screen problem when moving too fast.

baiachen commented 2 years ago

确实存在这个问题 另外想请问下FlatList对应的是 WaterfallList组件, SectionList 对应的是 LargeList 是吗,

bolan9999 commented 2 years ago

确实存在这个问题 另外想请问下FlatList对应的是 WaterfallList组件, SectionList 对应的是 LargeList 是吗,

不是,LargeList相当于SectionList,WaterfallList是瀑布流组件

bolan9999 commented 2 years ago

注意看WaterfallList的动画

bolan9999 commented 2 years ago

1: Dev Operating System window 10

2: Target OS android 11 inifnix note 10, redemi note 8 android 10, samsumg A51 android 11, samsung j2 android 8 3: real device

4: package.json

 "react-native": "0.64.2",
 "react-native-spring-scrollview": "^3.0.1-rc.5",
 "react-native-largelist-v3": "^3.1.0-rc.1",

5.

DocumentScreen.js

import React, {useEffect, useState} from 'react'
import {SafeAreaView,View, StyleSheet, Platform} from 'react-native'
import {WaterfallList } from 'react-native-largelist-v3'
import {useSelector, useDispatch} from 'react-redux';
import Item from '../components/DocumentItem'
import { BUTTONRADIUS, COLORS, FONTS } from '../constants';
const DocumentScreen = () => {
    const {allconverteddocuments} = useSelector(state => state.ConvertedDocumentsReducer)
    const [data, setData] = useState([])

    useEffect(() => {
        getfiledetails(allconverteddocuments).then((data) => {
            setData(data)
        })
    },[])

    const renderItem = (item, index) => (
        <Item item={item} />
    )

    return(
    <View style={styles.mainView}>

        <SafeAreaView>
            <WaterfallList 
                data={data}
                bounces={false}
                numColumns={1}
                renderItem={renderItem}
                heightForItem={() => 70}
            />
        </SafeAreaView>
    </View>
    )
}

export default DocumentScreen;

const styles = StyleSheet.create({
    mainView: {
        backgroundColor:"#ffffff",
        flexGrow:1
    },
    RowView:{
        backgroundColor:"#eee",
        paddingVertical:5,
        marginHorizontal:5, 
        alignItems:"center", 
        paddingHorizontal:20 , 
        marginVertical:5,
        borderRadius:BUTTONRADIUS.medium,
        elevation: 4,
    },
    nameText:{
        color:COLORS.lightblack,
        fontFamily:FONTS.medium
    },
    typeText:{
        color:COLORS.gray,
        fontSize:12,
        fontFamily:FONTS.regular
    }
})

DocumentItem.js

import React, {useState,memo, useCallback} from 'react'
import {Text, StyleSheet, TouchableOpacity,  } from 'react-native'
import { Col, Row, Grid } from "react-native-easy-grid";
import Share from 'react-native-share';
import WORDICON from '../assets/ppticon.svg'
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'
import {getfilesize, getdate} from '../services'
import { BUTTONRADIUS, COLORS, FONTS, SCREENS, width } from '../constants';
import * as RootNavigation from '../navigations/Rootnavigator'
import Dialog from "react-native-dialog";
import Menu, {
    MenuProvider,
    MenuOptions,
    MenuOption,
    MenuTrigger,
  } from 'react-native-popup-menu';
const Item = ({ item }) => {
    const [state, setState] = useState(false)
    const [isModalVisible, setModalVisible] = useState(false);
    const [deleteModal, setDeleteModal] = useState(false)
    const [rename , setRename] = useState("")

    const onOptionSelect = (value) => {
        if(value == "openfile"){
            openFile();
        }else if(value == "sharefile"){
            ShareFile()
        }else if(value == "rename"){
            RenameFile()
        }else if(value == "delete"){
            DeleteFileFunction()
        }
        setState(false);
    }

    const openFile = () => {
        RootNavigation.navigate(SCREENS.VIEWPDFSCREEN, {path:item.path})
    }

    const ShareFile = useCallback(function () {
        Share.open({
            url: `file://${item.path}`,
            type: 'application/pdf',
        }).then((result) => {
            console.log(result)
        }).catch((err) =>{

            if(err.message == "User did not share"){

            }else{
                alert('Some Error Occured please try again');
            }
        });
    }, []); 

    const RenameFile = () => {
        setModalVisible(true)
    }

    const onTriggerPress = () => {
        setState(true);
    }

    const  onBackdropPress = () =>  {
        setState(false);
    }

    const RenameFileFunction = () => {
        setModalVisible(false)
    }

    const DeleteFileFunction = () => {
        setDeleteModal(!deleteModal)
    }

    return (
        <Grid>
            <Row style={styles.RowView}>
                <Col size={1}>
                    <WORDICON width={40} height={40} />
                </Col>
                <Col size={4.5} style={{paddingVertical:10,}}>
                    <Row style={{justifyContent:"space-between", width:width}}>
                        <Col size={10}>
                            <Text numberOfLines={1} style={styles.nameText} >{item.filename}</Text>
                        </Col>

                    </Row>

                    <Row>    
                        <Col size={1}>
                            <Text style={styles.typeText} >{getfilesize(item.size)}</Text>
                        </Col>
                        <Col size={2}>
                            <Text style={styles.typeText}>{getdate(item.lastModified)}</Text>
                        </Col>                    
                    </Row>
                </Col>
                <Col size={.7} style={{justifyContent:"center", alignItems:"flex-end"}}>
                    <Menu
                        opened={state}
                        onBackdropPress={() => onBackdropPress()}
                        onSelect={value => onOptionSelect(value)}>
                        <MenuTrigger >
                            <TouchableOpacity onPress={() => onTriggerPress()}>
                                <MaterialCommunityIcons name={"dots-vertical"} size={26} />
                            </TouchableOpacity>
                        </MenuTrigger>
                        <MenuOptions 
                            style={styles.menuView} 
                            optionsContainerStyle={styles.menuView}>

                            <MenuOption value={"openfile"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"file-pdf"} size={16} color={COLORS.lightblack}/>
                                <Text style={{...styles.menuText, marginLeft:5,}}>Open File</Text>
                            </MenuOption>
                            <MenuOption value={"sharefile"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"share-variant"} size={16} color={COLORS.lightblack}/>
                                <Text style={{...styles.menuText, marginLeft:5,}}>Share File</Text>
                            </MenuOption>
                            <MenuOption value={"rename"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"rename-box"} size={16} color={COLORS.lightblack}/>
                                <Text style={{...styles.menuText, marginLeft:5,}}>Rename</Text>
                            </MenuOption>
                            <MenuOption value={"delete"} style={styles.menuOptionsStyle}>
                                <MaterialCommunityIcons name={"delete"} size={16} color={COLORS.danger}/>
                                <Text style={{...styles.menuText,color:COLORS.danger, marginLeft:5,}}>Delete</Text>
                            </MenuOption>

                        </MenuOptions>
                   </Menu>
                </Col>
            </Row>
            <Dialog.Container visible={isModalVisible}>
                <Dialog.Title>Rename File</Dialog.Title>
                <Dialog.Description>
                    Please Enter File Name
                </Dialog.Description>
                <Dialog.Input 
                    value={rename}
                    onChangeText={(text) => setRename(text)}
                />
                <Dialog.Button label="Cancel" style={{color:"red"}} onPress={() => setModalVisible(false)} />
                <Dialog.Button label="OK" onPress={() => RenameFileFunction()} />
            </Dialog.Container>

            <Dialog.Container visible={deleteModal}>
                <Dialog.Title>Delete File</Dialog.Title>
                <Dialog.Description>
                    Are Your Sure 
                </Dialog.Description>
                <Dialog.Button label="Cancel" onPress={() => setDeleteModal(false)} />
                <Dialog.Button label="OK" style={{color:"red"}}  onPress={() => DeleteFileFunction()} />
            </Dialog.Container>
        </Grid>

    )}
export default memo(Item) ;

const styles = StyleSheet.create({
    mainView: {
        backgroundColor:"#ffffff",
        flexGrow:1
    },
    RowView:{
        backgroundColor:"#eee",

        marginHorizontal:5, 
        alignItems:"center", 
        paddingHorizontal:10 , 
        marginVertical:5,
        borderRadius:BUTTONRADIUS.medium,
        elevation: 4,
    },
    nameText:{
        color:COLORS.lightblack,
        fontFamily:FONTS.medium
    },
    typeText:{
        color:COLORS.gray,
        fontSize:12,
        fontFamily:FONTS.regular
    },
    menuText:{
        color:COLORS.lightblack,
        fontSize:12,
        fontFamily:FONTS.regular
    },
    menuView:{
        backgroundColor:"#fff", 
        maxWidth:100, 
        borderRadius:10
    },
    menuOptionsStyle:{
        paddingHorizontal:10, 
        paddingVertical:5,
        borderBottomWidth:0,
        flexDirection:"row",

    }
})

tried this with memo and without memo but same result

Here is a sample video

20210812_144335.mp4

我在尝试使用reanimated重新写LargeList的新版本。

baiachen commented 2 years ago

确实存在这个问题 另外想请问下FlatList对应的是 WaterfallList组件, SectionList 对应的是 LargeList 是吗,

不是,LargeList相当于SectionList,WaterfallList是瀑布流组件

FlatList 大列表使用您的那个组件比较合适呢?

bolan9999 commented 2 years ago

没有FlatList对应的,LargeList更改数据结构和参数就能完成FlatList的需求