Skip to content

Instantly share code, notes, and snippets.

View louis-young's full-sized avatar
💻
Probably building something with React 😄

Louis Young louis-young

💻
Probably building something with React 😄
View GitHub Profile
@louis-young
louis-young / index.tsx
Created December 7, 2023 12:14
Generic select input React component
import { type ChangeEvent, useState } from "react";
type SelectInputOption<TOptionValue> = {
label: string;
value: TOptionValue;
};
interface SelectInputProps<TOptionValue> {
options: Array<SelectInputOption<TOptionValue>>;
selectedValue: TOptionValue;
@louis-young
louis-young / formatter.js
Created November 21, 2023 08:35
ESLint formatter
module.exports = (results) => {
const byRuleId = results.reduce((map, current) => {
for (const { column, line, ruleId } of current.messages) {
if (!map[ruleId]) {
map[ruleId] = [];
}
const occurrence = `${current.filePath}:${line}:${column}`;
map[ruleId].push(occurrence);
}
@louis-young
louis-young / index.ts
Last active September 6, 2023 16:53
C# LINQ method analogs in TypeScript
const singleOrDefault = <TElement, TDefaultValue>(
array: ReadonlyArray<TElement>,
predicate: (element: TElement) => boolean,
defaultValue: TDefaultValue
): TElement | TDefaultValue => {
if (array.length === 0) {
throw new Error("The source sequence is empty.");
}
const element = array.find(predicate);
@louis-young
louis-young / index.ts
Last active July 25, 2023 21:24
Lunchtime LINQ challenges
/**
* https://markheath.net/post/lunchtime-linq-challenge
*/
interface GetSecondsFromMinutesAndSecondsParameters {
minutes: number;
seconds: number;
}
const getSecondsFromMinutesAndSeconds = ({
@louis-young
louis-young / index.tsx
Created July 19, 2023 15:01
Asynchronous React component
import type { ReactNode } from "react";
interface AsynchronousComponentProps<TData> {
children: (data: NonNullable<TData>) => ReactNode;
data: TData;
isLoading: boolean;
loadingFallback: ReactNode;
hasError: boolean;
errorFallback: ReactNode;
}
@louis-young
louis-young / index.ts
Last active May 25, 2023 16:32
useDebouncedValue
import { useEffect, useState } from "react";
export const useDebouncedValue = <TValue>(value: TValue, delay: number) => {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedValue(value);
}, delay);
@louis-young
louis-young / index.tsx
Created March 22, 2023 14:08
Infinite Scroll
import { useRef } from "react";
import { useIntersectionObserver } from "../../hooks/useIntersectionObserver";
import type { InfiniteScrollProps } from "./types";
export const InfiniteScroll = ({
loadMoreFunction,
isLoadingMore,
loadingMoreMessage,
hasLoadedEverything,
loadedEverythingMessage,
@louis-young
louis-young / index.tsx
Created March 22, 2023 14:07
useIntersectionObserver
import { useEffect } from "react";
import type { UseIntersectionObserverParameters } from "./types";
export const useIntersectionObserver = ({
observableRef,
callback,
options,
}: UseIntersectionObserverParameters) => {
useEffect(() => {
const intersectionObserver = new IntersectionObserver(
@louis-young
louis-young / index.ts
Created February 24, 2023 09:47
Safe context hook creator function
import { type Context, useContext } from "react";
import { invariant } from "../invariant";
export const createSafeContextHook = <TContextValue>(
context: Context<TContextValue>,
displayName: string
) => {
return () => {
const contextValue = useContext(context);
@louis-young
louis-young / index.tsx
Created November 7, 2022 14:35
useImperativeHandle with TypeScript and function components
import { forwardRef, useImperativeHandle, useRef } from "react";
export interface VideoProps {
source: string;
}
export interface VideoRef {
play: () => void;
pause: () => void;
}