简体   繁体   English

一遍又一遍地调用函数?

[英]Function called over and over again?

I've got a Pagination component in NextJS which looks like:我在 NextJS 中有一个Pagination组件,如下所示:

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:分页呈现并按预期工作:

分页

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.但是当我打开网络检查器时,我看到在generatePages函数中声明的这条语句console.log(url)被一遍又一遍地打印,这让我认为我的组件被一遍又一遍地渲染。

I added then:我当时补充说:

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

and removed the call to generatePages();并删除了对generatePages(); that I had before the return statement.我在 return 声明之前。 That stoped the message printing from appearing multiple times but now the pages on my component are not being displayed:这阻止了消息打印多次出现,但现在我的组件上的页面没有显示:

组件未正确呈现

I tried passing pages array as dependency to useEffect but that didn't make any difference.我尝试将pages数组作为依赖项传递给useEffect ,但这没有任何区别。

Any ideas what's going on?有什么想法吗?

EDIT编辑

For debugging purposes I've completely removed generatePages and updated my return value to be:出于调试目的,我完全删除了generatePages并将我的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>
    )

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.如您所见,我只是使用通过props传递的任何数据创建组件,并将{ console.log('here') }添加到返回中,以查看组件是否从父组件多次呈现。 That seems to be the case.情况似乎如此。 I was expecting to see here printed only once but it's being printed infinitely.我期待看到here只打印一次,但它被无限打印。

The parent component where Paging is being used is:使用Paging的父组件是:

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 .它只是一个带有Paging组件的简单表格,但我无法弄清楚是什么导致了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 开发工具中得到了输出,它不断地反复打印消息:

chrome 开发工具

on the other I've got my terminal open, which is also printing the message, but it only prints it twice:另一方面,我打开了终端,它也在打印消息,但它只打印了两次:

终端输出

which one is correct?哪一个是正确的?

尝试完全删除依赖数组,这样useEffect就没有第二个参数

您应该将pages存储在状态中,并且只在挂载时调用generatePages

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

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