Skip to main content

sometechblog.com

You don’t need a boilerplate for Next.js and Prisma

Originally the plan was to get familiar with Next.js and Prisma by making a simple boilerplate for it. Turns out a few commands is all it takes to generate a basic working app. Let’s get started and add Next.js:

npx create-next-app my-app

To add Typescript run touch tsconfig.json && yarn dev and Next.js will generate the needed files and install packages. Then add Prisma:

yarn add -D @prisma/cli
yarn prisma init

Prisma created a .env file with the database connection url. dotenvenc npm package can be used to generate an encrypted .env.enc file containing the production variables. Locally .env can be filled by hand (Primsa requires a .env file and doesn’t support having separate for .env.production and .env.staging).

Lightweight and flexible React hook to animate height change

Hiding or showing a element with React is as simple as an if statement deciding whether to print it or not. However often you want to be able to animate the transition, so that it smoothly closes or opens. To avoid cluttering the various components with this animation logic, extract the logic into a hook:

/**
 * Returns the variables needed to animate a open and close functionality via height
 * @param  {Boolean} isOpen:   boolean is the element initially open
 * @param  {Number}  duration: number duration in ms
 */
function useHeightAnimation(isOpen = false, duration = 350) {
  const contentRef = React.useRef(); // Inner wrapper that keeps the height if the outer animated is closed
  const [height, setHeight] = React.useState(isOpen ? 'auto' : 0);

  const handleClick = () => {
    const contentRect = contentRef.current.getBoundingClientRect();

    // Set the height so the element has an initial height to transition from
    setHeight(`${contentRect.height}px`);

    // Set the new desired height, either 0px or full height from the innerRef
    setTimeout(() => setHeight(height === 0 ? `${contentRect.height}px` : 0));

    setTimeout(
      () => {
        if (height === 0) {
          // Set the height to "auto" to prevent issues with resizing when fully opened
          setHeight('auto');
        }
      },
      duration,
      height,
    );
  };

  return { height, handleClick, contentRef };
}

The hook can be used like:

AbortController with redux-thunk and redux-saga

Features that allow the user to fire multiple requests quickly and where only the latest request is relevant, should build in an abort controller. A typical example of this is a search filter allowing the user to quickly select and deselect filters. With each clicked filter the application will fire another request to server and update the search results. As requests for previously selected filters are irrelevant, it makes no sense for the browser trying to resolve them all. On the contrary it can slow down the application considerably, especially if the requests payload is large and/or the Internet connection slow. Not to mention to avoid racing conditions.

Deploying Gatsby on a VPS

Although it is clearly not in fashion at the moment, deploying websites on a VPS (virtual private server) or regular server for that matter, without any containerization and orchestration is both fast and easy. I have been running my private VPS (with Ubuntu 16.06) for years without much sweat. Using the command line to install and configure a server is both easy and powerful once you know the basic. No need to bother with a fancy UI layer or the limitions it often imposes.