一遍又一遍地调用的功能?

发布于 2025-02-08 21:37:34 字数 8176 浏览 2 评论 0原文

我在NextJs中有一个分页组件,看起来很好

import Pagination from 'react-bootstrap/Pagination';
import Router from "next/router";
import {useEffect} from "react";

export { Paging }

function Paging(props) {

    let pages = []

    const generatePages = () => {
        for (let page = 1; page <= props.paginator.totalPages; page++) {
            let url = `/${props.source}?page=${page}&per_page=${props.paginator.perPage}`
            console.log(url)
            pages.push(
                <Pagination.Item key={page} active={page == props.paginator.page } onClick={() => Router.push(url)}>
                    { page }
                </Pagination.Item>
            );
        }
    }

    generatePages();

    return (
        <div id="pagination">
            <div className={"pagination-component"}>
            <Pagination>
                { props.paginator.prevPage != null &&
                    <Pagination.Prev onClick={() => Router.push(props.paginator.prevPage)} />
                }

                { pages }

                { props.paginator.nextPage != null &&
                    <Pagination.Next onClick={() => Router.push(props.paginator.nextPage)}/>
                }
            </Pagination>
            </div>
            <div className={"total-pages"}>
                Showing {props.paginator.perPage} out of { props.paginator.totalCount }
            </div>
        </div>
    )
}

。分页呈现并按预期工作:

“分页”

但是当我打开Web Inspector时,我看到此语句console.log(url)GeneratePages 函数一遍又一遍地打印,这使我认为我的组件一遍又一遍地呈现。

然后我添加:

useEffect(() => {
        generatePages();
    }, []);

并将调用删除到generatePages();之前返回语句之前的调用。这阻止了消息打印多次出现,但是现在我的组件上的页面尚未显示:

=“ https://i.sstatic.net/2728r.png” alt =“ component未正确渲染”>

我尝试传递pages array作为依赖关系使用,但这没有任何区别。

有什么想法是怎么回事?

编辑

用于调试目的,我完全删除了generatePages,并更新了我的return> return值为:

return (
        <div id="pagination">
            <div className={"pagination-component"}>
            <Pagination>
                { props.paginator.prevPage != null &&
                    <Pagination.Prev onClick={() => Router.push(props.paginator.prevPage)} />
                }

            { console.log('here') }

                { props.paginator.nextPage != null &&
                    <Pagination.Next onClick={() => Router.push(props.paginator.nextPage)}/>
                }
            </Pagination>
            </div>
            <div className={"total-pages"}>
                Showing {props.paginator.perPage} out of { props.paginator.totalCount }
            </div>
        </div>
    )

如您所见通过props传递的任何数据,并添加了{console.log('there there')}到返回,以查看是否从父零件中多次渲染组件。 情况似乎就是这样。我期望在这里看到仅打印一次,但它是无限打印的。

使用paping的父组件是:

import Table from 'react-bootstrap/Table';
import { HiOutlineTrash, HiOutlinePencil } from "react-icons/hi";
import { getAllGenres } from "../../api/genre";
import Link from 'next/link'
import Button from "react-bootstrap/Button";
import useStore from "../../stores";
import Alert from "react-bootstrap/Alert";
import { Paging } from "../../components/Pagination";

export default function Genres({ genres, pagination }) {

    const alerts = useStore((state) => state.alerts)
    const removeAllAlerts = useStore((state) => state.removeAllAlerts);

    const setShow = (show=false) => {
        removeAllAlerts();
    }

    // automatically close any open alerts after 10 seconds
    (() => setTimeout(setShow, 10000))();

    return (
        <>
            { alerts.length > 0 &&
            <Alert variant="success" onClose={() => setShow(false)} dismissible>
                <p>
                    { alerts[0] }
                </p>
            </Alert>
            }

            <div className={"page-title-section"}>
                <h2 className={"page-title"}>Genres</h2>
                <div className={"add-new-top"}>
                    <Link href={"/genres/new"}>
                        <Button variant="dark">Add New Genre</Button>
                    </Link>
                </div>
            </div>
            <Table striped bordered hover>
                <thead>
                <tr>
                    <th>Name</th>
                    <th>Description</th>
                    <th>Parent</th>
                    <th>Active</th>
                    <th>Created At</th>
                    <th/>
                </tr>
                </thead>
                <tbody>
                { genres.data && genres.data.map(genre => (
                    <tr key={genre.id}>
                        <td>
                            <Link href={`/genres/${genre.slug}`}>
                                { genre.name }
                            </Link>
                        </td>
                        <td>{ genre.description }</td>
                        <td>{ genre.parent }</td>
                        <td>{ genre.active ? "Yes" : "No" }</td>
                        <td>{ genre['created_at'] }</td>
                        <td>
                            <Link href={"/"}>
                                <a className={"action-btn edit-btn"}><HiOutlinePencil /></a>
                            </Link>
                            <Link href={"/"}>
                                <a className={"action-btn remove-btn"}><HiOutlineTrash /></a>
                            </Link>
                        </td>
                    </tr>
                ))}
                </tbody>
            </Table>

            <Paging paginator={pagination} source={"genres"} />
        </>
    )
}

/**
 * getServerSideProps gets all server side data before the page actually loads
 * @returns {Promise<{props: {genres: void}}>}
 */
export const getServerSideProps = async (context) => {

    // extract from query params in context data needed for pagination
    const page = context.query.page;
    const perPage = context.query.perPage;

    let genres = {}
    const res = await getAllGenres(page, perPage);

    if (res.data !== undefined) {
        genres = res.data
    }

    // build pagination object
    let pagination = {
        totalPages: res.data["total_pages"],
        totalCount: res.data["total_count"],
        perPage: res.data["per_page"],
        page: res.data["page"],
        nextPage: res.data["next_page_link"],
        prevPage: res.data["prev_page_link"],
    }

    return {
        props: {
            genres,
            pagination,
        }
    };
};

它只是一个简单的表,带有paping component,但我无法弄清楚是什么原因导致分页。

但是目前令我感到困惑的是,我得到了两组结果:一方面,我在Chrome Dev工具中获得了输出,该工具不断地打印消息:

”

我的另一个我的终端也打开了,它也正在打印消息,但它仅将其打印两次:

“终端输出”

哪个是正确的?

I've got a Pagination component in NextJS which looks like:

import Pagination from 'react-bootstrap/Pagination';
import Router from "next/router";
import {useEffect} from "react";

export { Paging }

function Paging(props) {

    let pages = []

    const generatePages = () => {
        for (let page = 1; page <= props.paginator.totalPages; page++) {
            let url = `/${props.source}?page=${page}&per_page=${props.paginator.perPage}`
            console.log(url)
            pages.push(
                <Pagination.Item key={page} active={page == props.paginator.page } onClick={() => Router.push(url)}>
                    { page }
                </Pagination.Item>
            );
        }
    }

    generatePages();

    return (
        <div id="pagination">
            <div className={"pagination-component"}>
            <Pagination>
                { props.paginator.prevPage != null &&
                    <Pagination.Prev onClick={() => Router.push(props.paginator.prevPage)} />
                }

                { pages }

                { props.paginator.nextPage != null &&
                    <Pagination.Next onClick={() => Router.push(props.paginator.nextPage)}/>
                }
            </Pagination>
            </div>
            <div className={"total-pages"}>
                Showing {props.paginator.perPage} out of { props.paginator.totalCount }
            </div>
        </div>
    )
}

this works fine. The pagination is rendered and working as expected:

Pagination

but when I open the web inspector I see that this statement console.log(url) which is declared in the generatePages function is printed over and over again, which leads me to think that my component is being rendered over and over again.

I added then:

useEffect(() => {
        generatePages();
    }, []);

and removed the call to generatePages(); that I had before the return statement. That stoped the message printing from appearing multiple times but now the pages on my component are not being displayed:

component not rendered correctly

I tried passing pages array as dependency to useEffect but that didn't make any difference.

Any ideas what's going on?

EDIT

For debugging purposes I've completely removed generatePages and updated my return value to be:

return (
        <div id="pagination">
            <div className={"pagination-component"}>
            <Pagination>
                { props.paginator.prevPage != null &&
                    <Pagination.Prev onClick={() => Router.push(props.paginator.prevPage)} />
                }

            { console.log('here') }

                { props.paginator.nextPage != null &&
                    <Pagination.Next onClick={() => Router.push(props.paginator.nextPage)}/>
                }
            </Pagination>
            </div>
            <div className={"total-pages"}>
                Showing {props.paginator.perPage} out of { props.paginator.totalCount }
            </div>
        </div>
    )

as you can see I'm just creating the component with whatever data is passed via props and added { console.log('here') } to the return to see whether the component was being rendered multiple times from the parent component.
That seems to be the case. I was expecting to see here printed only once but it's being printed infinitely.

The parent component where Paging is being used is:

import Table from 'react-bootstrap/Table';
import { HiOutlineTrash, HiOutlinePencil } from "react-icons/hi";
import { getAllGenres } from "../../api/genre";
import Link from 'next/link'
import Button from "react-bootstrap/Button";
import useStore from "../../stores";
import Alert from "react-bootstrap/Alert";
import { Paging } from "../../components/Pagination";

export default function Genres({ genres, pagination }) {

    const alerts = useStore((state) => state.alerts)
    const removeAllAlerts = useStore((state) => state.removeAllAlerts);

    const setShow = (show=false) => {
        removeAllAlerts();
    }

    // automatically close any open alerts after 10 seconds
    (() => setTimeout(setShow, 10000))();

    return (
        <>
            { alerts.length > 0 &&
            <Alert variant="success" onClose={() => setShow(false)} dismissible>
                <p>
                    { alerts[0] }
                </p>
            </Alert>
            }

            <div className={"page-title-section"}>
                <h2 className={"page-title"}>Genres</h2>
                <div className={"add-new-top"}>
                    <Link href={"/genres/new"}>
                        <Button variant="dark">Add New Genre</Button>
                    </Link>
                </div>
            </div>
            <Table striped bordered hover>
                <thead>
                <tr>
                    <th>Name</th>
                    <th>Description</th>
                    <th>Parent</th>
                    <th>Active</th>
                    <th>Created At</th>
                    <th/>
                </tr>
                </thead>
                <tbody>
                { genres.data && genres.data.map(genre => (
                    <tr key={genre.id}>
                        <td>
                            <Link href={`/genres/${genre.slug}`}>
                                { genre.name }
                            </Link>
                        </td>
                        <td>{ genre.description }</td>
                        <td>{ genre.parent }</td>
                        <td>{ genre.active ? "Yes" : "No" }</td>
                        <td>{ genre['created_at'] }</td>
                        <td>
                            <Link href={"/"}>
                                <a className={"action-btn edit-btn"}><HiOutlinePencil /></a>
                            </Link>
                            <Link href={"/"}>
                                <a className={"action-btn remove-btn"}><HiOutlineTrash /></a>
                            </Link>
                        </td>
                    </tr>
                ))}
                </tbody>
            </Table>

            <Paging paginator={pagination} source={"genres"} />
        </>
    )
}

/**
 * getServerSideProps gets all server side data before the page actually loads
 * @returns {Promise<{props: {genres: void}}>}
 */
export const getServerSideProps = async (context) => {

    // extract from query params in context data needed for pagination
    const page = context.query.page;
    const perPage = context.query.perPage;

    let genres = {}
    const res = await getAllGenres(page, perPage);

    if (res.data !== undefined) {
        genres = res.data
    }

    // build pagination object
    let pagination = {
        totalPages: res.data["total_pages"],
        totalCount: res.data["total_count"],
        perPage: res.data["per_page"],
        page: res.data["page"],
        nextPage: res.data["next_page_link"],
        prevPage: res.data["prev_page_link"],
    }

    return {
        props: {
            genres,
            pagination,
        }
    };
};

it is just a simple table with the Paging component, but I can't figure out what's causing the multiple rendering of Paging.

But it's confusing me a lot at the moment is that I'm getting two sets of results: On one hand I've got the output in Chrome Dev Tools which keeps printing the message over and over:

chrome dev tools

on the other I've got my terminal open, which is also printing the message, but it only prints it twice:

terminal output

which one is correct?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

呢古 2025-02-15 21:37:35

尝试完全删除依赖项数组,以便没有第二个参数useeffect

Try remove the dependency array completely so there is no second argument to the useEffect

愁杀 2025-02-15 21:37:35

您应该在状态中存储页面,并且仅在Mount上呼叫GeneratePages

You should store pages in state and only call generatePages on mount.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文