DEV Community

Chan
Chan

Posted on • Updated on

Dev log

feature: it's user interactions that store, update and manipulate data. It processes the data from UI to database to store it, and it extracts some data from database and process them to transfer them to the users.
component does nothing about this, it's just about navigation. so I'll put them just right there.

changing color animation

layout: client component renders server components(or client components) as props.

Building progress animation

  1. changing color on button click: impossible since we cannot transfer props to the children. If we change them to client components, we're bound to give up all the performance benefits since all the rendered components become client components.
  2. changing the color on pathname

AutoAnimate

new update: AutoAnimate juggles elements when you use the same values for the array. Since it just works, I can create an array based on the current pathname.

font optimization in client components

Link component

Using Link optimizes the performance by prefetching the route. That is why they recommend using <Link /> components rather than useRouter() hook.

Enum to array

you can extract the values of enum using Object.values(Enum).

Setting up Zustand

  • global store shouldn't be used anymore; Multiple requests have their store using contexts instead of persisting them as a module state.
  • Both Server components render and Client components render. Since their outputs are different(store is set to default values in server components, hydration errors are thrown(local data storage, local fetch). By initializing the Store in SSR, it can keep

Should I use Form elements?

  • If you get data across multiple pages and only send data to the server on the last page. In this situation, is it recommended to use form elements for each page?
  • There is no standard saying that form elements must include control elements and a submit button.
  • w3.org actually says it's even better to split a long form into smaller pieces. Therefore, it looks like it's a good practice to use form elements across multiple pages.

Why @vis.gl/react-google-maps?

Library Comparison Table

  • Can draw on the map
  • Still being maintained by the community
  • Only 3 bugs discovered
  • Use hook to be in sync with the google maps state

Environment variables

Next.js will load environment variables from .env.local file.

  • If the name of an environment variable doesn't start with NEXT_PUBLIC, it is only accessible on the server. That means if a client component attempts to access it, it'll be undefined. Therefore, the rendered result would be different from the server and there might be a hydration error.
  • If the name of environment variable starts with NEXT_PUBLIC, Next.js replaces all the process.env.[variable] with the given value. That's why client components can also access environment variables.

.refine
When you need to customize with your own rules, you can use .refine() method.
some methods take errorMap instead of errorMessage itself.

const getEnvVariable = (key: string) => {
  console.log(key); // "BASE_URL"
  console.log(process.env[key]); // undefined
  console.log(process.env["BASE_URL"]); // http://localhost:3000

  if (process.env[key] === undefined) {
    throw new Error(`Environment variable is undefined`);
  }
  return process.env[key];
};
Enter fullscreen mode Exit fullscreen mode

Why??

MSW Troubleshooting

Hot Module Reloading problems caused by Next.js Architecture

If you're using next.js, you must run msw on the client and server side. The problem comes into play when you change the handler of MSW. Next.js will not refresh on handler updates. Here's why.
Next.js 14 manages two processes. One is a long-term process and it's used for updating RootLayout. The other one is a short-term process used for updating relatively small routes. Since MSW is registered as a global module, the long-term process manages MSW. However, processes don't share memory. Therefore, Next.js doesn't refresh the short-term process.

Strategic Decision

I still decided to use MSW for mocking APIs because Hot Module Reloading is not a serious problem. Since I'll develop each component using Storybook in isolation, the dev server doesn't need fresh updates. So I'll keep using MSW to see the result in the dev server when all the components get together.

Instrumention

If you want to run some code every time Next.js starts running, you can register() it. This feature is typically used for integrating Next.js and logging/monitoring tools.

Cannot find module msw/node

You should set up next.config.js to enable instrumentation.

module.exports = {
  experimental: {
    instrumentationHook: true,
  }
}
Enter fullscreen mode Exit fullscreen mode

However, I got "Cannot find module msw/node" error even though I set it up with the option. The doc says 'Place the file in the root of your application or inside an src folder if using on'. I followed the Feature-Sliced Design's convention, which looks like the following image.

Directory Structure

When I set up Next.js initially, I chose the root directory option, so I thought "Cannot find module 'msw/node'" was thrown, and after many trials and errors, I found out I should have placed the file in the /src directory.

Cannot find module msw/browser

To make the example code more tidy, I refactored it with 'early return' approach.

export async function enableMocking() {
  // early return doesn't work
  if (
    typeof window === "undefined" ||
    process.env.NODE_ENV !== "development"
  ) {
    return;
  }
  const { worker } = await import("@/mocks/browser");
  await worker.start();
}
Enter fullscreen mode Exit fullscreen mode

It kept throwing Cannot find module msw/browser. I attempted to change the path of the dynamic import to the relative one without using the path alias and set up package.json. However, it came down to this early return pattern. If I avoid this approach, my app runs with the error on the client side.

// Next.js picks up instrumentation.ts file in /src directory
export async function enableMocking() {
  // early return doesn't work
  if (
    typeof window !== "undefined" &&
    process.env.NODE_ENV === "development"
  ) {
    const { worker } = await 
    import("@/mocks/browser");
    await worker.start();
  }
}
Enter fullscreen mode Exit fullscreen mode

As a side note: I had the same problem with the server-side configuration. If you know something about this problem, please let me know.

Top comments (0)