The useSWR
hook from swr works everywhere if I explicitly enter the fetcher.
const { data } = useSWR("http://...", fetcher);
However, if I used swr global configuration as shown below, the useSWR
only works in First
page but not in HeaderLayout
component. I did some debugging and found out that in HeaderLayout
doesn't receive the value from swr global configuration (SWRConfig
in _app.tsx
) even though it is wrapped inside.
I followed this doc https://nextjs.org/docs/basic-features/layouts#per-page-layouts for the page layout implementation
// _app.tsx
type NextPageWithLayout = NextPage & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
};
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
function MyApp({ Component, pageProps }: AppPropsWithLayout) {
const getLayout = Component.getLayout ?? ((page) => page);
return (
<SWRConfig
value={{
fetcher: (resource, init) =>
fetch(resource, init).then((res) => res.json()),
}}
>
{getLayout(<Component {...pageProps} />)}
</SWRConfig>
);
}
// pages/first
const First = () => {
const [searchInput, setSearchInput] = useState("");
const router = useRouter();
const { data } = useSWR("http://...");
return (
<div>...Content...</div>
);
};
First.getLayout = HeaderLayout;
// layout/HeaderLayout
const HeaderLayout = (page: React.ReactElement) => {
const router = useRouter();
const { project: projectId, application: applicationId } = router.query;
const { data } = useSWR(`http://...`);
return (
<>
<Header />
{page}
</>
);
};
Helpful links:
https://nextjs.org/docs/basic-features/layouts#per-page-layouts
https://swr.vercel.app/docs/global-configuration
CodePudding user response:
Your First.getLayout
property should be a function that accepts a page
and returns that page wrapped by the HeaderLayout
component.
First.getLayout = function getLayout(page) {
return (
<HeaderLayout>{page}</HeaderLayout>
)
}
The HeaderLayout
is a React component, its first argument contains the props
passed to it. You need to modify its signature slightly to match this.
const HeaderLayout = ({ children }) => {
const router = useRouter();
const { project: projectId, application: applicationId } = router.query;
const { data } = useSWR(`http://...`);
return (
<>
<Header />
{children}
</>
);
};