Skip to content

Latest commit

 

History

History
895 lines (545 loc) · 17.1 KB

migrating-from-react-use.story.mdx

File metadata and controls

895 lines (545 loc) · 17.1 KB

import { Meta } from '@storybook/addon-docs';

One of @react-hookz/web's primary goals is to replace react-use, the no longer maintained project @react-hookz/web grew out of.

A note on missing hooks

The most common react-use hooks have already been ported to @react-hookz/web. You can track our progress porting the rest of react-use's hooks in this issue.

If there is a react-use hook you need that isn't ported yet, please comment there - or even better, make a PR!

In the meantime, feel free to use both @react-hookz/web and react-use in tandem.

Installation

See our README.

Migrating Hooks

Sensors

useBattery

Not implemented yet

useGeolocation

Not implemented yet

useHover

Not implemented yet

useHoverDirty

Not implemented yet

useHash

Location-related hooks will not be implemented. Instead, consider using one of the various routing libraries available.

useIdle

Not implemented yet

useIntersection

Implemented as useIntersectionObserver

OLD in react-use:

const intersection = useIntersection(elementRef, {
	root: rootRef,
	rootMargin: '0px',
	threshold: 1,
});

NEW in @react-hookz/web:

const intersection = useIntersectionObserver(elementRef, {
	root: rootRef,
	rootMargin: '0px',
	threshold: [0, 0.5],
});

useKey

See useKeyboardEvent

useKeyPress

See useKeyboardEvent

useKeyboardJs

See useKeyboardEvent

useKeyPressEvent

See useKeyboardEvent

useLocation

Location-related hooks will not be implemented. Instead, consider using one of the various routing libraries available.

useSearchParam

Location-related hooks will not be implemented. Instead, consider using one of the various routing libraries available.

useLongPress

Not implemented yet

useMedia

Implemented as useMediaQuery

No API changes, besides name change.

useMediaDevices

Not implemented yet

useMotion

Not implemented yet

useMouse

Not implemented yet

useMouseHovered

Not implemented yet

useMouseWheel

Not implemented yet

useNetworkState

Implemented as useNetworkState

No API changes, besides name change.

useOrientation

Not implemented yet

usePageLeave

Not implemented yet

useScratch

Not implemented yet

useScroll

Not implemented yet

useScrolling

Not implemented yet

useStartTyping

Not implemented yet

useWindowScroll

Not implemented yet

useWindowSize

Implemented as useWindowSize

useMeasure

Implemented as useMeasure

No API changes.

useSize

Use useMeasure instead.

createBreakpoint

No plans to implement

useScrollbarWidth

Not implemented yet

UI

useAudio

Not implemented yet

useClickAway

Implemented as useClickOutside)

No API changes, besides name change.

useCss

Not implemented yet

useDrop

Not implemented yet

useDropArea

Not implemented yet

useFullscreen

Not implemented yet

useSlider

Not implemented yet

useSpeech

Not implemented yet

useVibrate

Not implemented yet

useVideo

Not implemented yet

Animations

useRaf

Not implemented yet

useInterval

Implemented as useIntervalEffect

No API changes, besides name change.

useSpring

Not implemented yet

useTimeout

No plans to implement, rather use useTimeoutEffect and useRerender like this:

const rerender = useRerender();
const [cancel, reset] = useTimeoutEffect(rerender, 123);

useTimeoutFn

Implemented as useTimeoutEffect

API is backwards-compatible, minus the first isReady return value.

In order to replicate the old functionality, you can do the following:

const isReady = (React.useRef < boolean) | (null > false);

const [cancel, reset] = useTimeoutEffect(() => {
	isReady.current = true;
	console.log('Hello world');
}, 123);

const clear = () => {
	isReady.current = null;
	cancel();
};

const set = () => {
	isReady.current = false;
	reset();
};

// Use set and clear, same as in `react-use`.

useTween

Not implemented yet

useUpdate

Implemented as useRerender

No API changes, besides name change.

Side-effects

useAsync

Implemented as useAsync

OLD in react-use:

const { loading, value, error } = useAsync(async () => {
	const response = await fetch(url);
	const result = await response.text();
	return result;
}, [url]);

console.log(loading);
console.log(value);
console.log(error.message);

NEW in @react-hookz/web:

const [{ status, result, error }, { execute }] = useAsync(async () => {
	const response = await fetch(url);
	const result = await response.text();
	return result;
});

useMountEffect(execute);

console.log(status === 'loading');
console.log(result);
console.log(error.message);

useAsyncFn

Implemented as part of useAsync

OLD in react-use:

const [{ loading, value, error }, doFetch] = useAsync(async () => {
	const response = await fetch(url);
	const result = await response.text();
	return result;
}, [url]);

doFetch();

NEW in @react-hookz/web:

const [{ status, result, error }, { execute }] = useAsync(async () => {
	const response = await fetch(url);
	const result = await response.text();
	return result;
});

execute();

useAsyncRetry

Implemented as part of useAsync

OLD in react-use:

const { loading, value, error, retry } = useAsync(async () => {
	const response = await fetch(url);
	const result = await response.text();
	return result;
}, [url]);

retry();

NEW in @react-hookz/web:

const [{ status, result, error }, { execute }] = useAsync(async () => {
	const response = await fetch(url);
	const result = await response.text();
	return result;
});

execute();

useBeforeUnload

No plans to implement. Use useEventListener instead:

useEventListener(window, 'beforeunload', () => {
	/* do your stuff here */
});

useCookie

Implemented as useCookieValue

OLD in react-use:

const [value, set, remove] = useCookie('my-cookie');

console.log(value);
set('Hello world!', options);
remove();

NEW in @react-hookz/web:

const [value, set, remove] = useCookieValue('react-hookz', options);

console.log(value);
set('Hello world!');
remove();

NOTES:

  • js-cookies needs installed separately from @react-hookz/web to use useCookie
  • useCookie instances with the same key on the same page are synchronised. This synchronisation does not work across tabs or on changes that are triggered by third-party code.

useCopyToClipboard

Not implemented yet

useDebounce

@react-hookz/web has three options for debouncing, which we feel are both more ergonomic and flexible than react-use's implementation.

Depending on your use case, useDebouncedEffect, useDebounceCallback, or useDebouncedState may be more appropriate.

useError

Not implemented yet

useFavicon

Hooks that modify contents of the <head> element will not be implemented. Instead, consider using libraries such as react-helmet and react-helmet-async.

useLocalStorage

Implemented as useLocalStorageValue

Backwards compatible API, minus the raw option.

NOTE: useLocalStorage instances with the same key on the same page are synchronised. This synchronisation does not work across tabs or on changes that are triggered by third-party code.

useLockBodyScroll

Not implemented yet

useRafLoop

Not implemented yet

useSessionStorage

Implemented as useSessionStorageValue

Backwards compatible API, minus the raw option.

NOTE: useSessionStorage instances with the same key on the same page are synchronised. This synchronisation does not work across tabs or on changes that are triggered by third-party code.

useThrottle and useThrottleFn

@react-hookz/web has three options for throttling, which we feel are both more ergonomic and flexible than react-use's implementations.

Depending on your use case, useThrottledEffect, useThrottledCallback, or useThrottledState may be more appropriate.

useTitle

Hooks that modify contents of the <head> element will not be implemented. Instead, consider using libraries such as react-helmet and react-helmet-async.

Backwards compatiable API.

usePermission

Implemented as usePermission

No API changes.

Lifecycles

useEffectOnce

Was just an alias for useMountEffect - use that directly instead.

useEvent

Implemented as useEventListener

OLD in react-use:

useEvent(
	'mousemove',
	() => {
		setState(new Date());
	},
	window,
	{ passive: true }
);

NEW in @react-hookz/web:

useEventListener(
	window,
	'mousemove',
	() => {
		setState(new Date());
	},
	{ passive: true }
);

useLifecycles

No plans to implement

useMountedState

Implemented as useIsMounted

No API change, besides name change.

useUnmountPromise

Not implemented yet

usePromise

Not implemented yet

useLogger

Implemented as useLifecycleLogger

useMount

Implemented as useMountEffect

No API change, besides name change.

useUnmount

Implemented as useUnmountEffect

No API change, besides name change.

useUpdateEffect

Implemented as useUpdateEffect

No API changes.

useIsomorphicLayoutEffect

Implemented as useIsomorphicLayoutEffect

No API changes.

useDeepCompareEffect

Not implemented yet

useShallowCompareEffect

Not implemented yet

useCustomCompareEffect

Not implemented yet

State

createMemo

No plans to implement

createReducer

No plans to implement

createReducerContext

No plans to implement

createStateContext

No plans to implement

useDefault

No plans to implement, rather use useMediatedState like so:

const initialValue = 'world';
const defaultValue = 'you';
const [greeting, setGreeting] = useMediatedState(
	initialValue,
	(newValue) => newValue ?? defaultValue
);
console.log(`Hello ${greeting}`);

useGetSet

Not implemented yet

useGetSetState

Not implemented yet

useLatest

Implemented as useSyncedRef

No API changes, besides name change.

usePrevious

Implemented as usePrevious

No API changes.

usePreviousDistinct

Not implemented yet

useObservable

Not implemented yet

useRafState

Not implemented yet

useSetState

React.useState maybe used to achieve the same with minimal changes.

OLD in react-use:

const [state, setState] = useSetState({});

setState({ hello: 'world' });
setState({ foo: 'bar' });

NEW in @react-hookz/web:

const [state, setState] = useState({});

setState((current) => { ...current, hello: 'world' });
setState((current) => { ...current, foo: 'bar' });

useStateList

Not implemented yet

useToggle

Implemented as useToggle

No API changes.

useBoolean

Use useToggle instead

useCounter

Implemented as useCounter

useNumber

Use useCounter instead.

useList

Implemented as useList.

useUpsert

Use useList instead.

useMap

Implemented as useMap

OLD in react-use:

const [map, { set, remove, reset, setAll }] = useMap({
	hello: 'there',
});

console.log(JSON.stringify(map, null, 2));
set('some', 'thing');
remove('hello');
reset();
setAll({ hello: 'there', some: 'thing' });

NEW in @react-hookz/web:

const map = useMap(new Map([['hello', 'there']]););

console.log(JSON.stringify(Array.from(map), null, 2));
map.set("some", "thing");
map.delete("hello");
map.clear();
// There is no native `setAll` method on `Map`s, but we can create our own easily
const setAll = (values) => {
    map.clear();
    valuePairs.forEach((valuePair) => map.set(valuePair[0], valuePair[1]));
}
setAll([['hello', 'there']]);

NOTES: @react-hookz/web's implementation is the same signature as the native Map object, but its methods are wrapped to cause components to rerender with changes.

useSet

Implemented as useSet

OLD in react-use:

const [set, { add, reset, remove, has, toggle }] = useSet(new Set(['hello', 'world']));

console.log(JSON.stringify(Array.from(set), null, 2));
add(String(Date.now()));
reset();
remove('hello');
has('hello');
toggle('hello');

NEW in @react-hookz/web:

const set = useSet(['hello', 'world']);

console.log(JSON.stringify(Array.from(set), null, 2));
set.add(String(Date.now()));
set.clear();
set.delete('hello');
set.has('hello');
// There is no native `toggle` method on `Set`s, but we can create our own easily
const toggle = (value) => (set.has(value) ? set.delete(value) : set.add(value));
toggle('hello');

NOTES: @react-hookz/web's implementation is the same signature as the native Set object, but its methods are wrapped to cause components to rerender with changes.

useQueue

Not implemented yet

useStateValidator

Implemented as useValidator

OLD in react-use:

// outside of React component
const validator = (s) => {
  const isValid = !text.length || text.length % 2 === 1;

  const error = !isValid ? new Error("text length should be an odd length") : undefined,

  return [isValid, error]
};

-----
// inside of React component
const [text, setText] = useState("");
const [[isValid, error], revalidate] = useStateValidator(text, validator);

console.log(isValid);
console.log(error?.message);
revalidate();

NEW in @react-hookz/web:

const [text, setText] = useState("");

const validator =
  (d) => {
    const isValid = !text.length || text.length % 2 === 1;

    const error = !isValid ? new Error("text length should be an odd length") : undefined,

    d({
      isValid,
      error
    });
  }

const [validity] = useValidator(validator, [text]);

console.log(validity.isValid);
console.log(validity.error?.message);
// no manual revalidation needed

useStateWithHistory

Not implemented yet

useMultiStateValidator

See useValidator

useMediatedState

Implemented as useMediatedState

OLD in react-use:

const [state, setState] = useMediatedState((value) => value, '');

console.log(state);
setState('Hello world!');

NEW in @react-hookz/web:

const [state, setState] = useMediatedState('', (value) => value);

console.log(state);
setState('Hello world!');

useFirstMountState

Implemented as useFirstMountState

No API changes.

useRendersCount

Implemented as useRenderCount

No API changes.

createGlobalState

No plans to implement

useMethods

Not implemented yet

Miscellaneous

useEnsuredForwardedRef

Not implemented yet

ensuredForwardRef

Not implemented yet