Skip to content

Instantly share code, notes, and snippets.

View sstur's full-sized avatar

Simon Sturmer sstur

View GitHub Profile
@sstur
sstur / upload.ts
Last active January 9, 2023 08:05
type ReqInit = {
method?: 'PUT' | 'POST';
headers?: HeadersInit;
body: Blob | BufferSource | FormData | URLSearchParams | string;
signal?: AbortSignal;
onProgress?: (bytesLoaded: number, bytesTotal: number) => void;
};
export function upload(url: string, init: ReqInit) {
const { signal, onProgress, body } = init;

Polyfill ReadableStream making it always an async iterator:

ReadableStream.prototype[Symbol.asyncIterator] = function() {
  const reader = this.getReader();
  return {
    next: () => reader.read(),
    return: () => {
      reader.releaseLock();
    },
 };
import { useRef, useEffect, useCallback } from 'react';
export function useGetLatestValue<T>(value: T): () => T {
const valueRef = useRef(value);
useEffect(() => {
valueRef.current = value;
}, [value]);
return useCallback(() => valueRef.current, []);
}
function createErrorSubclass<T = string>(
name: string,
getMessage: (param: T | undefined) => string | undefined = (input) =>
input === undefined ? undefined : String(input),
ErrorClass: new () => Error = Error,
) {
if (!name.endsWith('Error')) {
throw new Error(`Invalid name "${name}"`);
}
return Object.defineProperties(
import crypto from 'crypto';
export function getRandomBytes(numBytes: number): Promise<Buffer> {
return new Promise((resolve, reject) => {
crypto.randomBytes(numBytes, (error, result) => {
error ? reject(error) : resolve(result);
});
});
}
import 'react-native';
import React from 'react';
import App from '../App';
// Note: test renderer must be required after react-native.
import { createRenderer } from 'react-test-renderer/shallow';
it('should render correctly', () => {
let renderer = createRenderer();
renderer.render(<App />);
import { useEffect, useState } from 'react';
let loadedScripts: Map<string, Promise<null>> = new Map();
export default function useScript(src: string) {
let [isLoaded, setLoaded] = useState(false);
useEffect(() => {
let promise = loadedScripts.get(src) || loadScript(src);
promise.then(() => {
setLoaded(true);
import { useCallback, useState, useRef } from 'react';
export function useDebounce<T>(initialValue: T, ms: number) {
let [value, setValue] = useState(initialValue);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let timeout = useRef<any>();
let debouncedSetter = useCallback(
(newValue: T) => {
clearTimeout(timeout.current);
timeout.current = setTimeout(() => {
export type JsonPrimitive = null | boolean | number | string;
export type JsonArray = Array<JsonValue>;
export type JsonObject = { [key: string]: JsonValue };
export type JsonValue = JsonPrimitive | JsonArray | JsonObject;
export function useStableCallback<T extends Array<unknown>, R>(
callback: (...args: T) => R,
): (...args: T) => R {
let ref = useRef(callback);
useLayoutEffect(() => {
ref.current = callback;
});
let stableCallback = useCallback((...args: T) => {
return ref.current(...args);
}, []);