Next.js utility for reusing getServerSideProps, getStaticProps and getInitialProps logics.
You can install it via npm
npm install --save next-composition
composeServerSideProps takes multiple getServerSideProps and composes them into a single function.
-
params.use
- Array of getServerSideProps to compose. Object returned from them will be shallowly merged and passed to the page. -
params.resolver
(optional, default:x => x
) - A callback function for interpolating the props before it's passed to the page.
import { composeServerSideProps } from 'next-composition';
const withAccount: GetServerSideProps = async (ctx) => {
const data = await fetch('/account');
return { props: { account: data } };
};
const withPosts: GetServerSideProps = async (ctx) => {
const data = await fetch('/posts');
return { props: { posts: data } };
};
export const getServerSideProps = composeServerSideProps({
use: [withAccount, withPosts],
});
export default function Page(props) {
// Results are available here
const { account, posts } = props;
}
If any of the functions in the use
return an object that contains either notFound
or redirect
, the first one will be used.
composeStaticProps takes multiple getStaticProps functions and composes them into a single function. Behaves like composeServerSideProps
but you can additionally specify revalidate
.
-
params.use
- Array of getStaticProps to compose. Object returned from them will be shallowly merged and passed to the page. -
params.resolver
(optional, default:x => x
) - A callback function for interpolating the props before it's passed to the page. -
params.revalidate
(optional, default:min
) - Could be one ofmin
,max
, or number. If a number specified, it will be used asrevalidate
. If you specifymin
(or max), the minimal number fromrevalidate
returned fromuse
will be used.
import { composeStaticProps } from 'next-composition';
const withAccount: GetStaticProps = async (ctx) => {
const data = await fetch('/account');
return { props: { account: data }, revalidate: 60 };
};
const withPosts: GetStaticProps = async (ctx) => {
const data = await fetch('/posts');
return { props: { posts: data }, revalidate: 30 };
};
export const getStaticProps = composeStaticProps({
use: [withAccount, withPosts],
revalidate: 'min', // `30` will be used in this case
});
export default function Page(props) {
// Results are available here
const { account, posts } = props;
}
composeInitialProps takes multiple getInitialProps functions and composes them into a single function.
-
params.use
- Array of getInitialProps to compose. Object returned from them will be shallowly merged and passed to the page. -
params.resolver
(optional, default:x => x
) - A callback function for interpolating the props before it's passed to the page.
import { composeInitialProps } from 'next-composition';
const withAccount = async (ctx) => {
const data = await fetch('/account');
return { account: data };
};
const withPosts = async (ctx) => {
const data = await fetch('/posts');
return { posts: data };
};
export default function Page(props) {
// Results are available here
const { account, posts } = props;
}
Page.getInitialProps = composeInitialProps({
use: [withAccount, withPosts],
});
You can specify resolver
function in composeServerSideProps
or composeStaticProps
that allows you to interpolate the result before it is passed to the page. For example, if you want to use the count of posts
as title
, you can do it like this:
import { composeServerSideProps } from 'next-composition';
const withPosts: GetServerSideProps = async (ctx) => {
const data = await fetch('/posts');
return { props: { posts: data } };
};
export const getServerSideProps = composeServerSideProps({
use: [withPosts],
resolver: (props) => ({
...props,
title: `${props.posts.length} posts - My blog`,
}),
});
export default function Page(props) {
const { account, posts, title } = props;
}
Next.js introduces a feature called middleware since v12.x which allows you to handle shared server side logic in a single module.
It's goal is kind of similar to next-composition
: sharing common logic among multiple pages. However, since _middleware
designed to be executed as edge function, it has some limitations such as it does not allow you to pass props to page components.
next-composition
is a set of utility and the entity is just a getServerSideProps and getStaticProps so you can use it just like other APIs without limitations.
composeServerSideProps and composeStaticProps can handle redirects and 404s in the same way as the Next.js API. You might want to know that:
- If some of the functions in
use
returnsnotFound
orredirect
, rest of the functions will be ignored. - If more than one of the functions in
use
returns a redirect or a 404, the very first one will be used in priority.
const withAccount: GetServerSideProps = async (ctx) => {
const data = await fetch('/account');
// If no account found, redirect to the login page
if (!data) {
return {
redirect: {
destination: '/login',
},
};
}
return { props: { account: data } };
};
// If you pass withAccount to the composeServerSideProps,
// other props will be ignored and redirects to the login page
export const getStaticProps = composeServerSideProps({
use: [withAccount, withPosts],
});