【问题标题】:How to use pagination with React router v6如何在 React 路由器 v6 中使用分页
【发布时间】:2022-06-15 03:54:09
【问题描述】:

我正在尝试使用 react router 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

感谢您的帮助!

【问题讨论】:

    标签: reactjs react-router


    【解决方案1】:

    您通过将路由状态保持在本地组件状态并仅更新本地组件状态来复制路由状态。相反,请确保将路由用作路由状态的真实来源,并使用编程路由和链接组件等工具来更新页面状态。

    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
    

    【讨论】:

      猜你喜欢
      • 2022-11-14
      • 2023-01-15
      • 2022-07-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-17
      • 2022-11-28
      • 1970-01-01
      • 2021-12-20
      相关资源
      最近更新 更多