Skip to content

Instantly share code, notes, and snippets.

View freddi301's full-sized avatar

Frederik Batuna freddi301

View GitHub Profile
@freddi301
freddi301 / useLocalStorage.ts
Last active October 11, 2019 19:21
useLocalStorage #react #hook
import { useState } from "react";
export function useLocalStorage<T>(key: string, initialValue: T) {
const [storedValue, setStoredValue] = useState(() => {
try {
const item = window.localStorage.getItem(key);
return item ? JSON.parse(item) : initialValue;
} catch (error) {
return initialValue;
}
@freddi301
freddi301 / useScheduledEffect.tsx
Created October 11, 2019 10:01
useScheduledEffect #react #hook
import { useEffect, useRef } from "react";
type TimeoutCallback = (timestamp: number) => void;
export function useScheduledEffect(
callback: TimeoutCallback,
timestamp: number | null,
) {
const savedCallback = useRef<TimeoutCallback | null>(callback);
@freddi301
freddi301 / useReferentialCallback.tsx
Created October 11, 2019 10:00
useReferentialCallback: do not rerender on callback intance change #react #hook
import React from "react";
export function useReferentialCallback<F extends (...args: any[]) => any>(
fn: F,
deps?: any[],
): F {
const fnRef = React.useRef<F>(fn);
React.useLayoutEffect(() => {
fnRef.current = fn;
}, deps); // eslint-disable-line
@freddi301
freddi301 / usePersistentState.tsx
Created October 11, 2019 09:59
usePersistentState LocalStorage/SessionStorage #react #hook
import React, { Dispatch, SetStateAction } from "react";
type ViolationMessage = string | (() => string);
function useStableValue<V>(
value: V,
message: ViolationMessage = "Violation: cannot change value between re-renders",
) {
const ref = React.useRef(value);
@freddi301
freddi301 / useMemoizedCallbacks.tsx
Created October 11, 2019 09:57
useMemoizedCallbacks #react #hook
import { useMemo } from "react";
import { memoize } from "lodash";
/**
* @description useful for callback that are passed to repeated component
* @example
* const makeRemove=useMemoizedCallback((date:Date)=>()=>{},String,[]);
* ...
* <ol>calendarEvents.map(calendarEvent => <li onClick={makeRemove(calendarEvent)}>{calendarEvent.toLocaleString()}</li>)</ol>
*/
@freddi301
freddi301 / useMediaQuery.tsx
Created October 11, 2019 09:56
useMediaQuery #react #hook
import React from "react";
/**
* Matches mediaquery, rerenders only when match changes
* @param query media query
*/
export function useMediaQuery(
query: string | null | false,
defValue: boolean = false,
) {
@freddi301
freddi301 / useInterval.tsx
Created October 11, 2019 09:56
useInterval #react #hook
/**
* This is an implementation of javascript's imperative setInterval API
* combined with React hooks' declarative approach.
*
* It is actually a replica of Dan Abramov's implementation described here:
* https://overreacted.io/making-setinterval-declarative-with-react-hooks/
*/
import { useEffect, useRef } from "react";
@freddi301
freddi301 / useExpiration.tsx
Created October 11, 2019 09:55
useExpiration: returns true if given timestamp is in the future #react #hook
import { useState, useEffect } from "react";
/** @description hook: returns true if given timestamp is in the future */
export function useExpiration(
timestamp: number | null | undefined,
): boolean {
const visible = timestamp != null && Date.now() <= timestamp;
const [, forceRerender] = useState(0);
useEffect(() => {
if (visible && timestamp != null) {
@freddi301
freddi301 / useDebubPropChanges.tsx
Created October 11, 2019 09:53
useDebugPropChanges #react #hook
import { useRef } from "react";
/**
* @description used for identify changes between re-renders
* @example
* const changedProps = useChanges(props)
* @example
* useChanges(props, changes => console.log(changes))
*/
export function useDebugPropsChanges<T extends Record<any, any>>(
@freddi301
freddi301 / useDebounce.tsx
Last active July 1, 2020 08:59
Debounced value #react #hook
import React from "react";
export default function useDebounce<T>(value: T, delay: number) {
const [debouncedValue, setDebouncedValue] = React.useState(value);
React.useEffect(() => {
const timeout = setTimeout(() => {
setDebouncedValue(value);
}, delay);