use*_*989 6 reactjs next.js swr
我正在使用useSWR来获取数据,然后使用这些数据,我想通过使用reduce 来获得总计。如果我 console.log 输出该值,它工作正常,但一旦我尝试使用该值设置状态,我就会收到“太可能重新渲染”消息。
import Admin from "../../../components/admin/Admin";
import { useRouter } from "next/router";
import styles from "../../../styles/Dashboard.module.css";
import { getSession, useSession } from "next-auth/client";
import { useState } from "react";
/* BOOTSTRAP */
import Col from "react-bootstrap/Col";
import Container from "react-bootstrap/Container";
import Row from "react-bootstrap/Row";
import Spinner from "react-bootstrap/Spinner";
import Table from "react-bootstrap/Table";
import useSWR from "swr";
import axios from "axios";
const General = () => {
const [session, loading] = useSession();
const [adults, setAdults] = useState(null);
const router = useRouter();
const { id } = router.query;
const fetcher = (url) =>
axios
.get(url, {
headers: { Authorization: "Bearer " + session.user.servertoken },
})
.then((res) => res.data);
const { data, error } = useSWR(
`http://localhost:8000/api/admin/general/${id}`,
fetcher
);
if (data) {
const adults = data.map((a) => a.adults);
const reducer = (accumlator, item) => {
return accumlator + item;
};
const totalAdults = adults.reduce(reducer, 0);
setAdults(totalAdults);
}
return (
<Admin>
<div className={styles.admin_banner}>
<Container fluid>
<Row>
<Col>
<h2>Bookings</h2>
<h6>
{adults}
</h6>
</Col>
</Row>
</Container>
</div>
<Container fluid>
<Row>
<Col>
<div className={styles.admin_container}>
{!error && !data && (
<Spinner animation="border" role="status">
<span className="sr-only">Loading...</span>
</Spinner>
)}
{!error && data && (
<Table responsive="md">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
{data &&
!error &&
data.map((d) => (
<tr key={d._id}>
<td>
{d.firstName} {d.lastName}
</td>
</tr>
))}
</tbody>
</Table>
)}
</div>
</Col>
</Row>
</Container>
</Admin>
);
};
export async function getServerSideProps(context) {
const session = await getSession({
req: context.req,
});
if (!session) {
return {
redirect: {
destination: "/admin",
permanent: false,
},
};
} else {
return { props: session };
}
}
export default General;
Run Code Online (Sandbox Code Playgroud)
men*_*t_a 10
您应该使用依赖于数据值的 useEffect,以便仅当数据在渲染之间发生更改时才可以更新它,接受的答案使用了 useEffect 内的 useSWR 挂钩,这是不正确的
例子:
const General = () => {
const [session, loading] = useSession();
const [adults, setAdults] = useState(null);
const router = useRouter();
const { id } = router.query;
const fetcher = (url) =>
axios
.get(url, {
headers: { Authorization: "Bearer " + session.user.servertoken },
})
.then((res) => res.data);
const { data, error } = useSWR(
`http://localhost:8000/api/admin/general/${id}`,
fetcher
);
useEffect(() => {
const adultsFetch = data.map((a) => a.adults);
const reducer = (accumlator, item) => {
return accumlator + item;
};
const totalAdults = adultsFetch.reduce(reducer, 0);
setAdults(totalAdults);
}, [data]);
}
Run Code Online (Sandbox Code Playgroud)
编辑:
您还可以使用 useMemo 挂钩,这样您甚至不再需要 useState,useMemo 会在每次数据依赖关系发生变化时重新计算成年人。
欲了解更多信息:https://reactjs.org/docs/hooks-reference.html#usememo
const General = () => {
const [session, loading] = useSession();
const router = useRouter();
const { id } = router.query;
const fetcher = (url) =>
axios
.get(url, {
headers: { Authorization: "Bearer " + session.user.servertoken },
})
.then((res) => res.data);
const { data, error } = useSWR(
`http://localhost:8000/api/admin/general/${id}`,
fetcher
);
const adults = useMemo(() => {
if (!data) return null;
const adultsFetch = data.map((a) => a.adults);
const reducer = (accumlator, item) => {
return accumlator + item;
};
const totalAdults = adultsFetch.reduce(reducer, 0);
return totalAdults;
}, [data]);
}
Run Code Online (Sandbox Code Playgroud)
小智 10
您可以通过添加第三个参数(选项)来实现此目的,如下所示:
const { data, error } = useSWR(
`http://localhost:8000/api/admin/general/${id}`,
fetcher,
{
revalidateOnFocus: false,
revalidateIfStale: false,
// revalidateOnReconnect: false, // personally, I didn't need this one
}
);
Run Code Online (Sandbox Code Playgroud)
它基本上缓存数据并防止一旦有缓存就重新验证。这是文档的链接。
或者,根据文档,useSWRImmutable从版本 1.0 开始,您可以使用 来获得与默认设置这些选项相同的结果。
import useSWRImmutable from "swr/immutable"
const { data, error } = useSWRImmutable(`http://localhost:8000/api/admin/general/${id}`, fetcher)
Run Code Online (Sandbox Code Playgroud)
Gh0*_*05d -1
问题是您的setAdults(totalAdults);数据检查导致了无限循环。React中的 Hook会导致组件重新渲染,所以实际发生的情况是
data为 true -->setAdults被触发 --> 重新渲染 -->data为 true --> ...
将您的逻辑移至useEffect挂钩中:
React.useEffect(() => {
const fetcher = url =>
axios
.get(url, {
headers: { Authorization: "Bearer " + session.user.servertoken },
})
.then(res => {
const adults = data.map(a => a.adults);
const reducer = (accumlator, item) => {
return accumlator + item;
};
const totalAdults = adults.reduce(reducer, 0);
setAdults(totalAdults);
});
useSWR(`http://localhost:8000/api/admin/general/${id}`, fetcher);
}, []);
Run Code Online (Sandbox Code Playgroud)
还要更新您的加载和错误检查。也许为两者创建一个新的状态变量。
| 归档时间: |
|
| 查看次数: |
11066 次 |
| 最近记录: |