繁体   English   中英

如何在 React 路由器 v6 中使用分页

[英]How to use pagination with React router v6

我正在尝试使用反应路由器 v6 实现分页。 分页本身正在工作,但每次刷新页面时都会返回第 1 页。我想在 url 中有分页号。 在这里它适用于第 1 页,但它不会在单击下一步按钮时更新页码。 我该如何解决这个问题?

这是我的代码:

function PostsList({ page, setPage }) {
    // Get data
    const [allPosts, setAllPosts] = useState([])
    const [pages, setPages] = useState(0)

    useEffect(() => {
        axios
            .get("/posts/posts")
            .then(res => {
                setAllPosts(res.data)
                setPages(Math.round(res.data.length / dataLimit))
            })
            .catch(err => console.log(err))
    }, [])

    // Pagination
    const dataLimit = 10
    const [currentPage, setCurrentPage] = useState(page)

    const goToNextPage = () => {
        setCurrentPage(page => page + 1)
        setPage(page => page + 1)
    }

    const goToPreviousPage = () => {
        setCurrentPage(page => page - 1)
        setPage(page => page - 1)
    }

    const changePage = e => {
        const pageNumber = Number(e.target.textContent)
        setCurrentPage(pageNumber)
    }

    const getPaginatedData = () => {
        const startIndex = currentPage * dataLimit - dataLimit
        const endIndex = startIndex + dataLimit
        return allPosts.slice(startIndex, endIndex)
    }

    const getPaginationGroup = () => {
        let start = Math.floor((currentPage - 1) / pages) * pages
        return new Array(pages).fill().map((_, i) => start + i + 1)
    }

    return (
        <Page>
            <ListPosts>
                {getPaginatedData().map(post => (
                    <Card post={post} key={post._id} />
                ))}
            </ListPosts>

            {getPaginationGroup().length > 0 && (
                <PaginationContainer>
                    <PaginationButton
                        onClick={goToPreviousPage}
                        disabled={currentPage === 1 && "disabled"}
                    >
                        <Icon
                            name="chevron-left"
                            color="currentColor"
                            size={16}
                        />
                    </PaginationButton>

                    {getPaginationGroup().map((item, i) => (
                        <PaginationButton
                            onClick={changePage}
                            className={currentPage === item && "active"}
                            key={i}
                        >
                            {item}
                        </PaginationButton>
                    ))}

                    <PaginationButton
                        onClick={goToNextPage}
                        disabled={currentPage === pages && "disabled"}
                    >
                        <Icon
                            name="chevron-right"
                            color="currentColor"
                            size={16}
                        />
                    </PaginationButton>
                </PaginationContainer>
            )}
        </Page>
    )
}

export default PostsList

和路线:

function Switch() {
    const [page, setPage] = useState(1)

    return (
        <Routes>
            <Route
                exact
                path="/posts/:page"
                element={<PostsList page={page} setPage={setPage} />}
            />
        </Routes>
    )
}

export default Switch

谢谢你的帮助!

您正在复制您的路线 state,方法是将其保存在本地组件 state 中,并且仅更新本地组件 state。 相反,请确保使用路由作为您的路由 state 的真实来源,并使用编程路由和链接组件等工具来更新您的页面 state。

function Switch() {
    return (
        <Routes>
            <Route
                exact
                {/* :page here the "state" of the route, we don't need to duplicate it. */} 
                path="/posts/:page"
                element={<PostsList />}
            />
        </Routes>
    )
}

export default Switch

有关编程导航的详细信息,请参阅: https://reactrouter.com/docs/en/v6/hooks/use-navigate

function PostsList() {
    // Get data
    const [allPosts, setAllPosts] = useState([])
    const [pages, setPages] = useState(0)

    useEffect(() => {
        axios
            .get("/posts/posts")
            .then(res => {
                setAllPosts(res.data)
                setPages(Math.round(res.data.length / dataLimit))
            })
            .catch(err => console.log(err))
    }, [])

    // Pagination
    const dataLimit = 10
    const { page: currentPage }  = useParams(); // from react-router, this is the `:page` parameter defined on the route. 
    const navigate = useNavigate(); 

    const goToNextPage = () => {
        navigate(`../${currentPage + 1}`) // you may have to tweak this based on your routing. See the link above about useNavigate()
    }

    const goToPreviousPage = () => {
        navigate(`../${currentPage - 1}`)
    }

    const changePage = e => {
        const pageNumber = Number(e.target.textContent)
        navigate(`../${pageNumber}`)
    }

    const getPaginatedData = () => {
        const startIndex = currentPage * dataLimit - dataLimit
        const endIndex = startIndex + dataLimit
        return allPosts.slice(startIndex, endIndex)
    }

    const getPaginationGroup = () => {
        let start = Math.floor((currentPage - 1) / pages) * pages
        return new Array(pages).fill().map((_, i) => start + i + 1)
    }

    return (
        <Page>
            <ListPosts>
                {getPaginatedData().map(post => (
                    <Card post={post} key={post._id} />
                ))}
            </ListPosts>

            {getPaginationGroup().length > 0 && (
                <PaginationContainer>
                    <PaginationButton
                        disabled={currentPage === 1 && "disabled"}
                    >
                    <NavLink to={`../${currentPage - 1}`}> // This might need to change slightly based on your needs, or could use the programatic approach above. Same for the other buttons below.
                        <Icon
                            name="chevron-left"
                            color="currentColor"
                            size={16}
                        />
                    </NavLink>
                    </PaginationButton>

                    {getPaginationGroup().map((item, i) => (
                        <PaginationButton
                            className={currentPage === item && "active"}
                            key={i}
                        >
                            {item}
                        </PaginationButton>
                    ))}

                    <PaginationButton
                        disabled={currentPage === pages && "disabled"}
                    >
                        <Icon
                            name="chevron-right"
                            color="currentColor"
                            size={16}
                        />
                    </PaginationButton>
                </PaginationContainer>
            )}
        </Page>
    )
}

export default PostsList

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM