- 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.jsdocs - runtime vars
serverRuntimeConfig(private, server),publicRuntimeConfig(public, client, server) docs - tutorial Youtube
- use
babel-plugin-superjson-nextandsuperjson-nextReadme - make sure it's
.babelrcwith.
- must use
pages/post/create/[[...id]].tsxand 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
.nextfolder
-
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.localis ignored (only.env.test.localis loaded)
# naming: .env.something123.local, ends with local
.env*.local- use dotenv-cli for .env.* files
- both
yarn devandyarn startshare same.nextfolder, so with dev you can run old prod build, delete it, forprisma migrate devtoo - 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