一遍又一遍地调用的功能?
我在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:
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:
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:
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尝试完全删除依赖项数组,以便没有第二个参数
useeffect
Try remove the dependency array completely so there is no second argument to the
useEffect
您应该在状态中存储
页面
,并且仅在Mount上呼叫GeneratePages
。You should store
pages
in state and only callgeneratePages
on mount.