- next-connect example
- youtube tutorial
- youtube code
- types for req, res: Github Readme
// this wil type all handler.get() .post() .use() ...
const handler = nc<NextApiRequest, NextApiResponse>();
// each .post() individually
interface ExtendedRequest {
user: string;
}
interface ExtendedResponse {
cookie(name: string, value: string): void;
}
handler.post<ExtendedRequest, ExtendedResponse>((req, res) => {
req.user = 'Anakin';
res.cookie('sid', '8108');
});
- actualy type
json(body: UserOrPost)
like this:
handler.get(async (req: NextApiRequest, res: NextApiResponse<PostWithAuthor>) => {
const post = await getPostWithAuthorById(getId(req));
res.status(200).json(post);
});
- ok to use in components, it's from context
- must do this to prevent undefined env vars with custom server
import { loadEnvConfig } from '@next/env';
const projectDir = process.cwd();
loadEnvConfig(projectDir);
- docs link
- .env.* (development, production, local - secret, test) files docs
- buildtime vars, env key in
next.config.js
docs - runtime vars
serverRuntimeConfig
(private, server),publicRuntimeConfig
(public, client, server) docs - tutorial Youtube
- use
babel-plugin-superjson-next
andsuperjson-next
Readme - make sure it's
.babelrc
with.
- must use
pages/post/create/[[...id]].tsx
and not `[[id]].tsx``
pages/post/create/[[id]].tsx
Error: Optional route parameters are not yet supported ("[[id]]").
- problem: client and server props not same, solution: delete
.next
folder
-
to avoid loading state in child components, easier error handling with suspense and ErrorBoundaries
-
all fetching in Views layer
-
React 18 FC and children stackoverflow
import * as React from 'react';
type Props = {
children?: React.ReactNode
};
const Component: React.FC<Props> = ({children}) => {...}
-
context and provider nice example
-
use
await queryClient.refetchQueries([QueryKeys.ME])
to refetch me after login, no need to pass refetch to context -
- Error: This Suspense boundary received an update before it finished hydrating. hydratation error, switched to client side rendering, startTransition useMe fetching in MeProvider must NOT be ABOVE pages solution - move MeProvider to PageLayout
-
- Error: inconsistent state Server: x, Client: y solution - check isMount {isMounted ? children : null} something not passed in getServerSideProps, and fetched in useQuery
/**
* Must NOT be used ABOVE pages (_app.tsx). Use it in Layouts.
* Only passes 'me'.
*/
const MeProvider: FC<ProviderProps> = ({ children }) => {
// prevent inconsistent state Server:x , Client:y error
const isMounted = useIsMounted();
const { data } = useMe();
return (
<MeContext.Provider value={{ me: data }}>
{isMounted ? children : null}
</MeContext.Provider>
);
};
- docs
- priority (lowest to highest):
.env
->.env.development, .env.production
->env.local
->.env.production.local
- for
NODE_ENV=test
,env.local
is ignored (only.env.test.local
is loaded)
# naming: .env.something123.local, ends with local
.env*.local
- use dotenv-cli for .env.* files
- both
yarn dev
andyarn start
share same.next
folder, so with dev you can run old prod build, delete it, forprisma migrate dev
too - actually bash terminal window has old env variable, open new terminal
- error:
warn - You have to use React 18 to use `experimental.reactRoot`.
Error: `experimental.runtime` requires `experimental.reactRoot` to be enabled along with React 18.
at Object.getBaseWebpackConfig [as default] (/home/username/Desktop/nextjs-prisma-boilerplate/node_modules/next/build/webpack-config.ts:355:11)
- solution:
process.env.__NEXT_REACT_ROOT = 'true';
in server.ts on top, stackoverflow - in custom server only
- this must use env var or SSR prop, must be same on SSR and CSR, no Javascript
// const baseUrl = process.env.NEXT_PUBLIC_BASE_URL; // with '/'
// const trimmedBaseUrl = baseUrl.replace(/\/$/, ''); // without
// baseUrl https://localhost:3001
// 'false' or url, not good
const baseUrl = isBrowser() && window.location.origin; // without '/'
- axios baseUrl works default, but let it have absolute path
const axiosInstance = axios.create({
// only if you need other than default
// baseURL: process.env.NEXT_PUBLIC_BASE_URL,
});
- custom loader (only for local images), for full urls just forward src and Image component works
export const uploadsImageLoader = ({ src, width, quality }: ImageLoaderProps) => {
// src starts with '/'
// use relative path for same domain
// const _src = src.replace(/^\//, '');
// return `${process.env.NEXT_PUBLIC_BASE_URL}${_src}?w=${width}&q=${quality || 75}`;
// if its full url https://... just forward it
return !isUrl(src) ? `${src}?w=${width}&q=${quality || 75}` : src;
};
- this will probably fail for google and facebook avatars...?
// google avatar works
https://lh3.googleusercontent.com/a/AATXAJxGLQSA1Qx-WpSBpKD3GxB9QoiEh=s96-c?w=256&q=75