Skip to content

Instantly share code, notes, and snippets.

View freddi301's full-sized avatar

Frederik Batuna freddi301

View GitHub Profile
@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);
@freddi301
freddi301 / useUndoReducer.ts
Last active October 26, 2019 17:10
Undoable Reducer react hooks #react #hook
function useUndoReducer<State, Action>(
reducer: (state: State, action: Action) => State,
initial: () => State[]
) {
const [index, setIndex] = useState(0);
const [history, setHistory] = useState(initial);
const state = history[index];
const dispatch = useCallback(
(action: Action) => {
const updated = history.slice(0, index + 1);
@freddi301
freddi301 / useUndoState.ts
Last active October 11, 2019 09:52
Unduoable state react hook #react #hook
function useUndoState<T>(initial: T) {
const [index, setIndex] = useState(0);
const [history, setHistory] = useState([initial]);
const state = history[index];
const setState = useCallback(
(update: (s: T) => T) => {
const updated = history.slice(0, index + 1);
updated.push(update(state));
setHistory(updated);
setIndex(index + 1);