Skip to content

Instantly share code, notes, and snippets.

View codemile's full-sized avatar

Nick Foscarini codemile

View GitHub Profile
@codemile
codemile / Button.tsx
Created July 19, 2021 12:20
Basic example of a Button component in ReactJs.
import {ButtonHTMLAttributes, forwardRef} from 'react';
export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
primary?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({className, primary, children, ...props}, ref) => {
return (
<button
@codemile
codemile / useClickOutside.tsx
Last active December 30, 2021 20:12
Hook that adds a click listener outside of an element.
import {DependencyList, useCallback, useEffect, useRef} from 'react';
export const useClickOutside = <T extends (...args: any[]) => any>(
cb: T,
dep: DependencyList
) => {
const ref = useRef<HTMLElement>(null);
// eslint-disable-next-line react-hooks/exhaustive-deps
const callback = useCallback(cb, dep);
@codemile
codemile / useArrayJoin.tsx
Created July 12, 2021 11:54
ReactJs hook that joins an Array of Elements with a separating Element.
export const useArrayJoin = (
arr: Array<JSX.Element>,
join: (key: number) => JSX.Element
) => {
return useMemo(() => {
return arr.reduce(
(acc: null | Array<JSX.Element>, next: JSX.Element, key) =>
acc === null ? [next] : [...acc, join(key), next],
null
);
@codemile
codemile / useCSSVariable.tsx
Created July 8, 2021 11:09
Hook that reads/writes #CSS variables. Turns a CSS variable into a useState() hook for your web components and lets you change them at run-time.
export const useCSSVariable = (name: string) => {
const [value, setState] = useState(
window.getComputedStyle(document.documentElement).getPropertyValue(name)
);
const setValue = useCallback(
(newValue: string) => {
setState(newValue);
document.documentElement.style.setProperty(name, newValue);
},
@codemile
codemile / useTickerTape.tsx
Created July 7, 2021 11:43
Hook that rotates the items of an Array over time like a news ticker tape.
const useTickerTape = <TType extends any>(
values: Iterable<TType>,
speed: number
) => {
const [tape, setTape] = useState([...values]);
useEffect(() => {
const id = setTimeout(() => {
const first = tape.shift();
setTape([...tape, first]);
@codemile
codemile / useDraggable.tsx
Created July 6, 2021 12:21
Hook that makes a DOM element draggable.
import {
MouseEventHandler,
RefObject,
useCallback,
useEffect,
useRef,
useState
} from 'react';
export type DraggableHandler = (coords: [number, number]) => void;
@codemile
codemile / useStateDebounce.tsx
Last active December 30, 2021 20:13
Hook that debounces useState() changes.
import {useCallback, useEffect, useRef, useState} from 'react';
export const useStateDebounce = <TType extends any>(ms: number, initialState?: TType) => {
const [state, setState] = useState(initialState);
const ref = useRef(0);
const setValue = useCallback(value => {
window.clearTimeout(ref.current);
ref.current = window.setTimeout(() => setState(value), ms);
}, [ms]);
useEffect(() => () => window.clearTimeout(ref.current), []);
@codemile
codemile / useStateJson.tsx
Last active December 30, 2021 20:14
Hook that stores a state value as a JSON string to prevent render updates when an object value is mutated but doesn't change.
import {useCallback, useMemo, useState} from 'react';
export const useStateJson = <TType extends any>(initialState?: TType) => {
const [json, setState] = useState<string>(
JSON.stringify(initialState ?? '')
);
const value = useMemo(() => JSON.parse(json), [json]);
const setValue = useCallback(
(next: TType) => setState(JSON.stringify(next ?? '')),
[]
@codemile
codemile / useStateBuffer.tsx
Last active December 30, 2021 20:14
Hook that records the history of state changes as an Array buffer upto a certain length.
import {useCallback, useState} from 'react';
export const useStateBuffer = <TType extends any>(
size: number,
initialState: TType
) => {
const [values, setState] = useState<Array<TType>>([initialState]);
const setValue = useCallback(
(next: TType) => setState([...values, next].slice(0, size)),
[values]
@codemile
codemile / useStateCount.tsx
Created June 29, 2021 18:44
Hook that increments a counter every time useState() is changed.
import {useCallback, useState} from 'react';
export const useStateCount = <TType extends any>(initialState?: TType) => {
const [[count, value], setState] = useState([0, initialState]);
const setValue = useCallback(
(next: TType) => setState([count + 1, next]),
[count]
);
return [count, value, setValue];
};