Skip to content

Instantly share code, notes, and snippets.

View ellemedit's full-sized avatar
🏠
Working from home

Marshall Han ellemedit

🏠
Working from home
  • Seoul
  • 20:24 (UTC +09:00)
View GitHub Profile
@ellemedit
ellemedit / NavigationIntercepter.tsx
Last active April 5, 2025 13:54
Next.js Navigation API intercepter
"use client";
// Next.js version of React ViewTransition fixture
// ref: https://github.com/facebook/react/blob/main/fixtures/view-transition/src/components/App.js
//
// Currently, it has a infinite rendering bug in React when you navigate for go or back
// wait for merging following PRs
// PR 1: https://github.com/facebook/react/pull/32821
// PR 2: https://github.com/vercel/next.js/pull/77856
//
@ellemedit
ellemedit / form.tsx
Created November 25, 2024 07:51
Form submit without resetting in React 19
export function Form() {
const [isPending, startTransition] = useTransition()
return (
<form
onSubmit={(event) => {
event.preventDefault()
const formData = new FormData(event.currentTarget)
startTransition(async () => {
await someAction(formData)
})
@ellemedit
ellemedit / refactor-react19.md
Created October 27, 2024 02:28
React 19 Refactor Prompt

React 19 Component Refactoring Guide

Import Optimization

Replace wildcard imports with specific named imports:

// ❌ Before
import * as React from "react";
@ellemedit
ellemedit / refactor-react19.md
Last active October 13, 2024 12:51
React18 Component -> React19 Component Refactor Prompt

With following context, refactor React components

Minimalistic Deps:

  • replace import * as React from "react" things to import { useState, use, ... } from React only required in the code

Prefer safe prop interface:

  • replace React.*HTMLAttributes to ComponentPropsWithRef<*>
  • replace type props to interface props. if props: A & B found, convert to interface Props extends A, B {} shape

Remove legacy forwardRef API:

@ellemedit
ellemedit / cache.ts
Created August 14, 2024 02:22
React cache like implementation
// copied from https://github.com/facebook/react/blob/8e60bacd08215bd23f0bf05dde407cd133885aa1/packages/react/src/ReactCacheImpl.js#L50
// but no react context
const rootCacheNode = new WeakMap<(...args: any[]) => any, CacheNode>();
const UNTERMINATED = 0;
const TERMINATED = 1;
const ERRORED = 2;
type CacheNode = {
@ellemedit
ellemedit / README.md
Last active August 5, 2024 08:42
[viem] type safe and maintainable contract call patterns with ABI

React 컴포넌트에서 컨트랙트를 호출하는 다음과 같은 코드가 있다고 가정해봅시다.

function buildCreateTokenTransaction({
  name,
  symbol,
  caipChainID,
  creatorAddress,
}: {
 caipChainID: CAIPChainID;
@ellemedit
ellemedit / generator.mjs
Last active July 30, 2024 06:21
NEXT_SERVER_ACTIONS_ENCRYPTION_KEY Generator
// you can run this on latest chrome browser and copy the result
function arrayBufferToString(buffer) {
const bytes = new Uint8Array(buffer)
const len = bytes.byteLength
// @anonrig: V8 has a limit of 65535 arguments in a function.
// For len < 65535, this is faster.
// https://github.com/vercel/next.js/pull/56377#pullrequestreview-1656181623
if (len < 65535) {
@ellemedit
ellemedit / README.md
Last active July 21, 2024 01:49
git shortcut

gacm: Git Add, Commit, and Push Function for Zsh

Overview

gacm (Git Add Commit Merge) is a Zsh function that simplifies the process of adding, committing, and optionally pushing Git changes. It combines git add ., git commit -m, and (optionally) git push into a single command, with an additional option for force push.

Installation

Add the following function to your ~/.zshrc file:

@ellemedit
ellemedit / FormField.browser-test.tsx
Last active July 15, 2024 04:53
[React 19][React Compiler] Accessible and Declarative Form Component
import { expect, test } from "vitest";
import { render, screen } from "@testing-library/react";
import {
FormDescription,
FormError,
FormField,
FormInput,
FormLabel,
@ellemedit
ellemedit / nextjs-mock.ts
Last active July 12, 2024 11:50
NextJS App Router cookie module mock with Bun/TypeScript
import { mock } from "bun:test";
import { ReadonlyRequestCookies } from "next/dist/server/web/spec-extension/adapters/request-cookies";
export function mockNextjsReadonlyCookie() {
mock.module("next/headers", () => {
const cookieMap = new Map<string, { name: string; value: string }>();
const cookies: ReadonlyRequestCookies = {
get: (nameOrCookie: string | { name: string }) => {
const name =
typeof nameOrCookie === "string" ? nameOrCookie : nameOrCookie.name;