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
  • 01:56 (UTC +09:00)
View GitHub Profile
@ellemedit
ellemedit / README.md
Last active June 29, 2022 10:02
Relay Resolver + TypeScript 쓰는 법

Relay Resolvers are still considered experimental. To use them you must ensure that the ENABLE_RELAY_RESOLVERS runtime feature flag is enabled, and that the enable_relay_resolver_transform feature flag is enabled in your project’s Relay config file.

라고 주장하고 아직 @types/relay-runtime에 타입이 반영 안 돼있기 때문에, 지금 사용하려면 relay-compiler 설정 + relay-runtime 런타임 설정 + relay-runtime 타입 확장을 해야 원활합니다.

// relay.config.js 또는 package.json 파일의 'relay' 컴파일러 설정
module.exports = {
  src: "./",
  artifactDirectory: "...",
 language: "typescript",
@ellemedit
ellemedit / mockNextRouter.tsx
Last active March 11, 2021 07:26
Next.js page level mocking renderer on Jest environment
import React from "react";
import { RouterContext } from "next/dist/next-server/lib/router-context";
import { NextRouter } from "next/router";
import { ReactNode } from "react";
export const makeMockNextRouterProvider = (router?: Partial<NextRouter>) => {
const mockRouter: NextRouter = {
basePath: "",
pathname: "/",
route: "/",
@ellemedit
ellemedit / README.md
Created January 12, 2021 01:56
Generic distribution problem in TypeScript

I don't know why distribution affect to problems.

@ellemedit
ellemedit / post.md
Last active December 18, 2021 11:02

제 경험이 당신의 next.js 프로젝트에 도움이 되거나 영감을 주면 좋겠습니다.

왜 퍼시스턴트 레이아웃이 필요한가요?

가장 근본적인 이유는 퍼시스턴트하지 않으면 모든 DOM 노드가 파괴되고 다시 생성된다는 점 입니다.

  1. 이전 페이지의 DOM Node가 버려지기 때문에 항상 DOM 상태를 잃어버립니다. 예를들어 레이아웃에 흔하게 있을 수 있는 검색창 입력, 네비게이션 메뉴의 포커스 상태가 페이지 이동마다 사라집니다.
  2. 당연하게도 CSS Transition이 불가능합니다. 애니메이션이 필요하다면 전혀 다른 방법으로 구현해야 합니다.

위 이유로 인해 애플리케이션의 사용성과 접근성이 떨어질 수 있습니다.

@ellemedit
ellemedit / combineRef.ts
Created April 23, 2020 09:07
sometimes you have to deal with multiple React.Refs. This is short helper
export const combineRef = <T>(...refs: (React.Ref<T> | string | void)[]) => {
// basically, JSX elements allows string refs for backward-compatiblity
// there's certain case runtime check needed
if (process.env.NODE_ENV !== "production" && refs.some((x) => typeof x === "string")) {
throw new Error("string refs are forbbiden");
}
return (node: T | null | undefined) => {
for (const ref of refs) {
if (!ref || typeof ref === "string") {
continue;
@ellemedit
ellemedit / useScreenEffect.ts
Created April 23, 2020 08:10
sometimes we need to care screen itself rather than intersectionObserver.
import * as React from 'react';
export function useScreenEffect(handler: () => void, deps: ReadonlyArray<any>) {
React.useLayoutEffect(() => {
const enhancedHandler = debounceToNextAnimationFrame(handler);
window.addEventListener("scroll", enhancedHandler, canUsePassive && { passive: true });
window.addEventListener("resize", enhancedHandler, canUsePassive && { passive: true });
enhancedHandler();
return () => {
@ellemedit
ellemedit / useScrollLock.ts
Last active April 7, 2020 09:49
React hook for body scroll lock
import React from "react";
import { enableBodyScroll, disableBodyScroll, BodyScrollOptions } from "body-scroll-lock";
export const useScrollLock = (
targetElement?: HTMLElement | Element | null | false,
bodyScrollOption?: BodyScrollOptions
) => {
React.useLayoutEffect(() => {
if (!targetElement) {
return;
@ellemedit
ellemedit / README.md
Last active March 17, 2021 01:07
suspenseAll: React Suspense hook sugar for fetching data concurrently.

suspenseAll

React Suspense hook sugar for fetching data concurrently.

Why this needed?

React suspense implementations is that catches a thrown promise in suspense tree. See useSWR and react-query. This blocks next hook till previous promise done if you don't prefetch.

@ellemedit
ellemedit / react.ts
Last active August 12, 2019 15:01
skipping to update state
React.useEffect(() => {
let canceled = false;
axios.post().then((res) => {
if (canceled) {
return;
}
setState(res.data);
});
return () => {
canceled = true;
atom settings