Skip to content

Instantly share code, notes, and snippets.

View shuding's full-sized avatar
❄️

Shu Ding shuding

❄️
View GitHub Profile
@shuding
shuding / random-branch.sh
Last active July 29, 2025 12:58
Raycast Random Branch
#!/bin/bash
# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Random Branch
# @raycast.mode silent
# Optional parameters:
# @raycast.icon 🎲
@shuding
shuding / polyfill.js
Created January 6, 2022 18:01
Modern iOS 100vh Polyfill
if (typeof window !== 'undefined') {
let onResize
if (window.visualViewport) {
onResize = () => {
const vh = window.visualViewport.height
document.documentElement.style.setProperty('--vh', `${vh}px`)
}
window.visualViewport.addEventListener('resize', onResize)
onResize()
} else {
@shuding
shuding / gist:40e6e13ab1dc3a3d86d8aacabb22dd5c
Created October 27, 2021 14:16
Spinner without 12 divs
<div class="spinner">
.spinner {
margin: 12px;
width: 28px;
height: 28px;
animation: spinner-rotating 1.2s infinite;
animation-timing-function: steps(12, end);
}
.spinner:before {
@shuding
shuding / swr-suspense-journey.md
Created September 14, 2021 12:18
The Journey of SWR and Suspense

The Journey of SWR and Suspense

We are trying to combine the idea of SWR ("stale-while-revalidate") and React Suspense together, and this write-up covers all our findings from this journey.

Background

When React Hooks launched, people started to rely on useEffect to initiate data fetching:

function User () {
import { unstable_serialize, useSWRConfig, SWRConfig } from 'swr'
import { useEffect } from 'react'
const counter = {}
const gc = useSWRNext => (key, fetcher, config) => {
const { cache } = useSWRConfig()
const serializedKey = unstable_serialize(key)
useEffect(() => {
counter[serializedKey] = (counter[serializedKey] || 0) + 1
function useWhyDoesItRerender(obj: any) {
for (let k in obj) {
useEffect(() => {
console.log('Value', k, 'changed to', obj[k]);
}, [obj[k]]);
}
}
// useWhyDoesItRerender({ propA, propB, stateC })
const delaySort = (arr) => {
const r = []
for (let x of arr) {
setTimeout(v => { r.push(v); if (r.length === arr.length) console.log(r) }, x, x)
}
}
// delaySort([3, 2, 1]) => [1, 2, 3]
@shuding
shuding / index.js
Created March 12, 2021 06:00
Next.js Image Example
import Image from 'next/image'
import { useState } from 'react'
function Home() {
const [load, setLoad] = useState(false)
return <>
<h1>Image Optimizer Home</h1>
{load ? <>
<Image src="https://source.unsplash.com/3840x512/weekly?water" width="3840" height="512" layout="intrinsic" />
<Image src="https://source.unsplash.com/3840x512/weekly?hill" width="3840" height="512" layout="intrinsic" />
@shuding
shuding / smoothscroll.js
Created January 2, 2020 19:33
SmoothScroll
// SmoothScroll
class SmoothScroll {
constructor() {
// the <main> element
this.DOM = {main: document.querySelector('main')};
// the scrollable element
// we translate this element when scrolling (y-axis)
this.DOM.scrollable = this.DOM.main.querySelector('div[data-scroll]');
// the items on the page
this.items = [];
// /swr/project.js
import useSWR, { mutate } from 'swr'

export async function fetchProject (id) {
  mutate(`/api/project/${id}`, fetch(`/api/project/${id}`))
}

export default function useProject (id) {
 // don't pass the fetcher so it won't fetch