【问题标题】:How can I stop duplicate array in my React - using infinite scroll?如何在我的 React 中停止重复数组 - 使用无限滚动?
【发布时间】:2022-01-26 13:15:21
【问题描述】:

我尝试过使用React-Infinite-Scroll-Component进行无限滚动

一切都像我想的那样完美,但问题是每当我更改流派,或按 F5 重新加载页面,或者不知何故,滚动条总是在最底部,我确实尝试使用 @987654328 修复它@ 但它仍然无法正常工作。

或者我以某种方式弄乱了代码,因为我试图非常努力地解决它,但我认为我执行得不够好。

代码非常很长,但这里是对我要在其中执行的操作的简要说明。

我收到一个定义为genreuseParams 的slug,例如actionadventure,然后我将其设置为状态genreAnime,然后我检查它是否是同一类型,它'将使用concat array 进行无限加载并将页面增加到1 以进行下一次加载,否则我将设置一个新的array 并将页面初始化回1,否则它将继续与旧数组合并以前的genretotalPage 设置为 91,每当它第二次渲染时,它会自动获取最新的 totalPage 并将其设置回来,所以它是安全的。

translateGenre 只是为了将流派翻译成文本,所以请不要打扰。

但是每当我刷新 (F5) 或浏览一点时,我会更改类型,它会得到相同 first array 的副本(由于警告,我看到它有 2 个相同的项目) .由于我的滚动条总是停留在“结束”或React-Infinite-Scroll-Componentdefault值,即0.8,这意味着当用户低于总高度的80%,会触发Infinite-Scroll-Componentnext函数

这是我的代码:

function AnimeGenre({ instance }) {
    const { genre } = useParams()

    const CancelToken = axios.CancelToken
    const source = CancelToken.source()

    const [animeList, setAnimeList] = useState([])
    const [genreAnime, setGenreAnime] = useState("")
    const [page, setPage] = useState(1)
    const [totalPage, setTotalPage] = useState(91)
    const [translateGenreAnime, setTranslateGenreAnime] = useState("")

    const getList = async () => {
        await instance
            .get(`/anime/${genre}?page=${page}`, {
                cancelToken: source.token,
            })
            .then((response) => {
                const newPage = page + 1
                setPage(newPage)
                const newList = response.data.data.map((anime) => ({
                    slug: anime.slug,
                    thumbnail: anime.thumbnail,
                    name: anime.name,
                    views: anime.views,
                }))
                setTotalPage(response.data.pagination.totalPage)
                setAnimeList((prev) => {
                    return [...new Set([...prev, ...newList])]
                })
            })
            .catch((thrown) => {
                if (axios.isCancel(thrown)) return
            })
    }    
    useEffect(() => {
        if (genre === genreAnime) {
            getList()
            translateGenre()
        } else {
            window.onbeforeunload = function () {
              window.scrollTo(0, 0)
             }
            window.scrollTo({
                top: 0,
            })
            setPage(1)
            setAnimeList([])
            setGenreAnime(genre)
        }

        return () => {
            source.cancel()
        }
    }, [genreAnime, genre])

    const translateGenre = () => {
        for (let i = 0; i < GENRES.length; i++) {
            if (genreAnime == GENRES[i].slug) {
                setTranslateGenreAnime(GENRES[i].name)
            }
        }
    }

    return (
        <>
            <div>
                <h1>ANIME {translateGenreAnime}</h1>
            </div>
            <div className="anime-list">
                <InfiniteScroll
                    initialScrollY={0}
                    style={{ overflow: "none" }}
                    dataLength={animeList.length}
                    next={getList}
                    hasMore={page === totalPage ? false : true}
                    loader={
                        <Row xs={1} sm={2} md={3} lg={4}>
                            {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((skeleton) => (
                                <Col key={skeleton}>
                                    <Card>
                                        <Card.Body style={{ maxHeight: "100%" }}>
                                            <Skeleton
                                                variant="rectangular"
                                                width="100%"
                                                height="192px"
                                                animation="wave"
                                                sx={{ bgcolor: "grey.900" }}
                                            />

                                            <Skeleton
                                                variant="text"
                                                animation="wave"
                                                sx={{ bgcolor: "grey.900" }}
                                            />
                                        </Card.Body>
                                    </Card>
                                </Col>
                            ))}
                        </Row>
                    }
                    endMessage={<h4>NO MORE THINGS TO LOAD</h4>}
                >
                    <Row xs={1} sm={2} md={3} lg={4}>
                        {animeList.map((anime) => (
                            <Col key={anime.slug}>
                                <Card>
                                    <div className="card-container">
                                        <Card.Img
                                            variant="top"
                                            src={anime.thumbnail}
                                            fluid="true"
                                        />
                                        <div className="overlay-card">
                                            <a className="icon">{<BsFillPlayFill size={40} />}</a>
                                        </div>
                                    </div>
                                    <Card.Body>
                                        <Card.Title>
                                            <TextTruncate
                                                line={2}
                                                element="span"
                                                truncateText="…"
                                                text={anime?.name}
                                            />
                                        </Card.Title>
                                    </Card.Body>
                                </Card>
                                <div className="w-100"></div>
                            </Col>
                        ))}
                    </Row>
                </InfiniteScroll>
            </div>
         <>
        }

只要scrollbar 停留在最顶部就可以正常工作,因为它不会超过高度的 80% 的阈值。

工作一:

当我浏览一下并更改 GENRE 时失败,因为滚动条停留在底部,然后稍后,它将执行 scrollTo(0,0)。这不是我想要的,我想要相反,它必须总是先到顶部......

第二个失败是当我按下 F5 按钮重新加载页面时。它会以某种方式显示非常奇怪(滚动条)。

更新:

我尝试禁用 smooth-scrolling behavior 并将滚动设置到顶部到具有导航栏的 header 组件中,这似乎是更合适的方法,它可以让我的滚动条在我想要的任何时候点击到顶部标题中的某些内容或使用 F5 刷新。

但是如果在第一次渲染时,我浏览页面并向下滚动太快,我会因为我达到阈值而出现重复错误,如果我等待第一次渲染,之前的函数仍在执行中完全加载,那我就没事了,有没有合适的方法可以无限滚动,请教我一些简单的方法,我觉得我太复杂了。

【问题讨论】:

    标签: javascript html css reactjs infinite-scroll


    【解决方案1】:

    我认为我做对了,但不太确定,它“目前”运行良好。

    这就是我的工作。

    代替

    const newPage = page + 1
    setPage(newPage)
    

    getList 函数中,我将其拆分为另一个名为scrollThreshold 的函数

    const scrollThreshold = () => {
        const newPage = page + 1
        setPage(newPage)
    }
    

    我设置

    const PAGE_NUMBER = 1
    

    在组件之外(否则我认为我应该使用 useRef 或者就这样保留它,以防万一)

    然后在useEffect,我实现了另外1 个依赖项,它是page 状态,每当我得到新的pagepage 状态更改,或genre 更改时,它将运行@987654332再次@。

    然后在InfiniteScroll 组件中,我将其从

    <InfiniteScroll>
    ...
    next={getList}
    ...
    </InfiniteScroll> 
    

    进入

    <InfiniteScroll>
    ...
    next={getList && scrollThreshold}
    ...
    </InfiniteScroll> 
    

    所以每当我向下滚动时,它都会触发 getList 和 scrollThreshold,通过分开,它不会像我的第一个代码那样聚集在一起。到目前为止它正在工作,我不知道这是否好。

    【讨论】:

      猜你喜欢
      • 2015-12-07
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 2021-04-27
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多