Security News
tea.xyz Spam Plagues npm and RubyGems Package Registries
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
next-data-hooks
Advanced tools
Readme
Use
getStaticProps
andgetServerSideProps
as react hooks
next-data-hooks
is a small and simple lib that lets you write React hooks for data queries in Next.js by lifting static props into React Context.
import { createDataHook } from 'next-data-hooks';
const useBlogPost = createDataHook('BlogPost', async (context) => {
const { slug } = context.params;
return; // ... get the blog post
});
function BlogPost() {
const { title, content } = useBlogPost();
return (
<>
<h1>{title}</h1>
<p>{content}</p>
</>
);
}
BlogPost.dataHooks = [useBlogPost];
export default BlogPost;
See the example in this repo for some ideas on how to organize your static data calls using this hook.
npm i next-data-hooks
or
yarn add next-data-hooks
At the root, add a .babelrc
file that contains the following:
{
"presets": ["next/babel"],
"plugins": ["next-data-hooks/babel"]
}
⚠️ Don't forget this step. This enables code elimination to eliminate server-side code in client code.
_app.tsx
or _app.js
import { AppProps } from 'next/app';
import { NextDataHooksProvider } from 'next-data-hooks';
function App({ Component, pageProps }: AppProps) {
const { children, ...rest } = pageProps;
return (
<NextDataHooksProvider {...rest}>
<Component {...rest}>{children}</Component>
</NextDataHooksProvider>
);
}
import { createDataHook } from 'next-data-hooks';
// this context is the GetStaticPropsContext from 'next'
// 👇
const useBlogPost = createDataHook('BlogPost', async (context) => {
const slug = context.params?.slug as string;
// do something async to grab the data your component needs
const blogPost = /* ... */;
return blogPost;
});
export default useBlogPost;
Note: For TypeScript users, if you're planning on only using the data hook in the context of
getServerSideProps
, you can import the provided type guard,isServerSidePropsContext
, to narrow the type of the incoming context.
import { createDataHook, isServerSidePropsContext } from 'next-data-hooks';
const useServerSideData = createDataHook('Data', async (context) => {
if (!isServerSidePropsContext(context)) {
throw new Error('This data hook only works in getServerSideProps.');
}
// here, the type of `context` has been narrowed to the server side conext
const query = context.req.query;
});
export default useServerSideData;
import ComponentThatUsesDataHooks from '..';
import useBlogPost from '..';
import useOtherDataHook from '..';
function BlogPostComponent() {
const { title, content } = useBlogPost();
const { other, data } = useOtherDataHook();
return (
<article>
<h1>{title}</h1>
<p>{content}</p>
<p>
{other} {data}
</p>
</article>
);
}
// compose together other data hooks
BlogPostComponent.dataHooks = [
...ComponentThatUsesDataHooks.dataHooks,
useOtherDataHooks,
useBlogPost,
];
export default BlogPostComponent;
getStaticProps
or getServerSideProps
.import { getDataHooksProps } from 'next-data-hooks';
import { GetStaticPaths, GetStaticProps } from 'next';
import BlogPostComponent from '..';
export const getStaticPaths: GetStaticPaths = async (context) => {
// return static paths...
};
// NOTE: this will also work with `getServerSideProps`
export const getStaticProps: GetStaticProps = async (context) => {
const dataHooksProps = await getDataHooksProps({
context,
// this is an array of all data hooks from the `dataHooks` static prop.
// 👇👇👇
dataHooks: BlogPostComponent.dataHooks,
});
return {
props: {
// spread the props required by next-data-hooks
...dataHooksProps,
// add additional props to Next.js here
},
};
};
export default BlogPostComponent;
routes
directoryNext.js has a very opinionated file-based routing mechanism that doesn't allow you to put a file in the /pages
folder without it being considered a page.
Simply put, this doesn't allow for much organization.
With next-data-hooks
, you can treat the /pages
folder as a folder of entry points and organize files elsewhere.
my-project
# think of the pages folder as entry points to your routes
├── pages
│ ├── blog
│ │ ├── [slug].ts
│ │ └── index.ts
│ └── shop
│ ├── category
│ │ └── [slug].ts
│ ├── index.ts
│ └── product
│ └── [slug].ts
|
# think of each route folder as its own app with it's own components and helpers
└── routes
├── blog
│ ├── components
│ │ ├── blog-index.tsx
│ │ ├── blog-post-card.tsx
│ │ └── blog-post.tsx
│ └── helpers
│ └── example-blog-helper.ts
└── shop
├── components
│ ├── category.tsx
│ ├── product-description.tsx
│ └── product.tsx
└── helpers
└── example-shop-helper.ts
/routes/blog/components/blog-post.tsx
import { createDataHook } from 'next-data-hooks';
// write your data hook in a co-located place
const useBlogPostData = createDataHook('BlogPost', async (context) => {
const blogPostData = // get blog post data…
return blogPostData;
});
function BlogPost() {
// use it in the component
const { title, content } = useBlogPostData();
return (
<article>
<h1>{title}</h1>
<p>{content}</p>
</article>
);
}
BlogPost.dataHooks = [useBlogPostData];
export default BlogPost;
/pages/blog/[slug].ts
import { GetStaticProps, GetStaticPaths } from 'next';
import { getDataHooksProps } from 'next-data-hooks';
import BlogPost from 'routes/blog/components/blog-post';
export const getStaticPaths: GetStaticPaths = {}; /* ... */
export const getStaticProps: GetStaticProps = async (context) => {
const dataHooksProps = getDataHooksProps({
context,
dataHooks: BlogPost.dataHooks,
});
return { props: dataHooksProps };
};
// re-export your component. this file is just an entry point
export default BlogPost;
👋 Note: the above is just an example of how you can use
next-data-hooks
to organize your project. The main takeaway is that you can re-export page components to change the structure andnext-data-hooks
works well with this pattern.
For smaller bundles, Next.js eliminates code that is only intended to run inside getStaticProps
.
next-data-hooks
does the same by a babel plugin that prefixes your data hook definition with typeof window !== 'undefined' ? <stub> : <real data hook>
.
This works because Next.js pre-evaluates the expression typeof window
to 'object'
in browsers. This will make the above ternary always evaluate to the <stub>
in the browser. Terser then shakes away the <real data hook>
expression eliminating it from the browser bundle.
If you saw the error Create data hook was run in the browser.
then something may have went wrong with the code elimination. Please open an issue.
👋 Note. There may be differences in Next.js's default code elimination and
next-data-hooks
code elimination. Double check your bundle.
FAQs
Use `getStaticProps` as react hooks
The npm package next-data-hooks receives a total of 17 weekly downloads. As such, next-data-hooks popularity was classified as not popular.
We found that next-data-hooks demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.
Security News
UnitedHealth Group disclosed that the ransomware attack on Change Healthcare compromised protected health information for millions in the U.S., with estimated costs to the company expected to reach $1 billion.