- useEventListener()
- useIsomorphicLayoutEffect()
- useReducerWithDeps()
- useStateWithDeps()
- contextualize()
- createGranularContext()
- createRequiredContext()
- wrapJSX()
- React ≥ 18
- TypeScript ≥ 5.4
const useEventListener: UseEventListener;Defined in: hooks/useEventListener.ts:154
Adds handler as a listener for the event eventName of target with the
provided options applied
The following call signatures are available:
function useEventListener(eventName, handler, options?): void;
function useEventListener(target, eventName, handler, options?): void;For the full definition of the hook's type, see UseEventListener.
If target is not provided, window is used instead.
If target is null or undefined, no event listener is added. This can be
used to add an event listener conditionally.
target can also be a ref object created with useRef. Beware
that in that case, changes to the ref's current value are only detected
correctly if a re-render happens at the same time it is changed. In other
words, it is required that whenever the ref's current value is updated,
some state in the component using the hook also changes at the same time.
You should never use a ref's current value as target directly as that
violates the rule of React that forbids reading refs during rendering (see
the refs rule
of eslint-plugin-react-hooks for details).
useEventListener('resize', () => {
console.log(window.innerWidth, window.innerHeight);
});
useEventListener(document, 'visibilitychange', () => {
console.log(document.visibilityState);
});
const buttonRef = useRef<HTMLButtonElement>(null);
useEventListener(buttonRef, 'click', () => console.log('click'));const useIsomorphicLayoutEffect: (effect, deps?) => void;Defined in: hooks/useIsomorphicLayoutEffect.ts:14
Identical to useLayoutEffect, except it does not result in
warnings when used on the server
| Parameter | Type |
|---|---|
|
|
|
|
|
|
void
function useReducerWithDeps<S, A>(
reducer,
initialState,
deps,
): [S, ActionDispatch<A>];Defined in: hooks/useReducerWithDeps.ts:64
useReducer hook with an additional dependency array deps that
resets the state to initialState when dependencies change
This hook is the reducer pattern counterpart of useStateWithDeps.
Due to React's limitations, a change in dependencies always causes two renders when using this hook. The result of the first render is thrown away as described in useState > Storing information from previous renders.
For motivation and examples, see react/react#33041.
The react-hooks/exhaustive-deps ESLint rule doesn't support hooks where
the dependency array parameter is at any other position than the second.
However, as we would like to keep the hook as compatible with useReducer as
possible, we don't want to artificially change the parameter's position.
Therefore, there will be no warnings about missing dependencies.
Because of that, additional caution is advised!
Be sure to check that no dependencies are missing from the deps array.
Related issue: react/react#25443.
Unlike eslint-plugin-react-hooks maintained by React's team, the unofficial
useExhaustiveDependencies rule provided for Biome by Biome's team
does actually have support for dependency arrays at other positions, see
useExhaustiveDependencies > Options > Validating dependencies.
| Type Parameter |
|---|
|
|
|
|
| Parameter | Type | Description |
|---|---|---|
|
|
( |
The reducer function that specifies how the state gets updated |
|
|
|
The value to which the state is set when the component is mounted or dependencies change It can also be a function that returns a state value. If the state is reset
due to a change of dependencies, this function will be passed the previous
state as its argument (will be |
|
|
|
Dependencies that reset the state to |
[S, ActionDispatch<A>]
function useStateWithDeps<S>(
initialState,
deps,
): [S, Dispatch<SetStateAction<S>>];Defined in: hooks/useStateWithDeps.ts:62
useState hook with an additional dependency array deps that
resets the state to initialState when dependencies change
Due to React's limitations, a change in dependencies always causes two renders when using this hook. The result of the first render is thrown away as described in useState > Storing information from previous renders.
For motivation and more examples, see react/react#33041.
type Activity = 'breakfast' | 'exercise' | 'swim' | 'board games' | 'dinner';
const timeOfDayOptions = ['morning', 'afternoon', 'evening'] as const;
type TimeOfDay = (typeof timeOfDayOptions)[number];
const activityOptionsByTimeOfDay: {
[K in TimeOfDay]: [Activity, ...Activity[]];
} = {
morning: ['breakfast', 'exercise', 'swim'],
afternoon: ['exercise', 'swim', 'board games'],
evening: ['board games', 'dinner'],
};
function Example() {
const [timeOfDay, setTimeOfDay] = useState<TimeOfDay>('morning');
const activityOptions = activityOptionsByTimeOfDay[timeOfDay];
const [activity, setActivity] = useStateWithDeps<Activity>(
(prev) => {
// Make sure activity is always valid for the current timeOfDay value,
// but also don't reset it unless necessary:
return prev && activityOptions.includes(prev) ? prev : activityOptions[0];
},
[activityOptions],
);
return '...';
}| Type Parameter |
|---|
|
|
| Parameter | Type | Description |
|---|---|---|
|
|
|
The value to which the state is set when the component is mounted or dependencies change It can also be a function that returns a state value. If the state is reset
due to a change of dependencies, this function will be passed the previous
state as its argument (will be |
|
|
|
Dependencies that reset the state to |
[S, Dispatch<SetStateAction<S>>]
function contextualize<Children>(children): ContextualizePipe<Children>;Defined in: misc/contextualize.tsx:68
An alternative way to provide context values to component trees that avoids ever-increasing indentation
A context-specific version of the more general wrapJSX function.
// Before:
return (
<CourseIdContext.Provider value={courseId}>
<DeckIdContext.Provider value={deckId}>
<FlashcardsContext.Provider value={flashcards}>
<EventHandlersContext.Provider value={eventHandlers}>
{children}
</EventHandlersContext.Provider>
</FlashcardsContext.Provider>
</DeckIdContext.Provider>
</CourseIdContext.Provider>
);
// After:
return contextualize(children)
.with(EventHandlersContext, eventHandlers)
.with(FlashcardsContext, flashcards)
.with(DeckIdContext, deckId)
.with(CourseIdContext, courseId)
.end();| Type Parameter |
|---|
|
|
| Parameter | Type | Description |
|---|---|---|
|
|
|
The children to contextualize |
ContextualizePipe<Children>
An object with the following properties:
with: a function that accepts a context providerProvider(or the context it belongs to) and a valuevaluefor that context as arguments and returnscontextualize(<Provider value={value}>{children}</Provider>)end: a function that returnschildren
function createGranularContext<Name, PartNames, Value, Props>(
name,
partNames,
providerHook,
): CreateRequiredContextWithCustomProviderResultProviderPart<Name, Props> & {
[K in string as `use${Capitalize<K>}`]: () => Value[K];
};Defined in: misc/createGranularContext.tsx:76
Generates multiple related contexts using createRequiredContext
and returns hooks for each of them as well as a provider component for all
of them that incorporates user-defined logic for populating context values
supplied in the providerHook argument
This function facilitates the application of the provider pattern in cases where the provider component provides values for multiple related contexts.
const { SearchProvider, useSearchQuery, useSetSearchQuery } =
createGranularContext(
'Search',
['searchQuery', 'setSearchQuery'],
({ initialQuery }: { initialQuery?: string }) => {
const [searchQuery, setSearchQuery] = useState(initialQuery ?? '');
return { searchQuery, setSearchQuery };
},
);
const App = () => (
<SearchProvider>
<Toolbar />
<Data />
</SearchProvider>
);
// Won't re-render when query changes because it only uses the query setter 🥳
const Toolbar = () => {
const setSearchQuery = useSetSearchQuery();
return (
<input onChange={(event) => setSearchQuery(event.currentTarget.value)} />
);
};
// Will re-render when query changes because it uses it 👍
const Data = () => {
const searchQuery = useSearchQuery();
// Fetch data and use searchQuery to filter it...
};| Type Parameter | Default type |
|---|---|
|
|
‐ |
|
|
‐ |
|
|
‐ |
|
|
{ } |
| Parameter | Type | Description |
|---|---|---|
|
|
|
A string that the provider component's display name is derived from |
|
|
|
An array of strings the underlying contexts' display names are derived from |
|
|
( |
A function that receives props passed to the provider component as its
argument and is used to populate the underlying contexts whose current values
it should return in an object mapping names from |
CreateRequiredContextWithCustomProviderResultProviderPart<Name, Props> & { [K in string as `use${Capitalize<K>}`]: () => Value[K] }
An object with the following properties:
`${capitalize(name)}Provider`(e.g.SearchProvider): the provider component`use${capitalize(partName)}`for each elementpartNameofpartNames(e.g.useSearchQuery,useSetSearchQuery): a hook that returns the current context value if one was provided, or throws an error otherwise
createRequiredContext,
CreateRequiredContextWithCustomProviderResultProviderPart
const createRequiredContext: CreateRequiredContext;Defined in: misc/createRequiredContext.tsx:230
Generates a context of type T and returns both a provider component and a
hook for that context where the hook will throw an error if no context value
has been provided
The advantages over vanilla createContext are that no default
value has to be specified, and that a meaningful context name is displayed in
dev tools instead of a generic Context.Provider.
The following call patterns are available:
createRequiredContext<T>()(name);
createRequiredContext(name, providerHook);When the first one is used, the standard React context provider is returned.
The type T has to be specified explicitly. Two calls are necessary due to
TypeScript's limitations.
The second pattern can be used when it is desired that the provider component
incorporates custom reactive logic for context value derivation. The type T
is inferred as the return type of providerHook which is the function where
that custom logic resides.
For the full definition of the function's type, see
CreateRequiredContext.
When multiple related values are provided by a single provider component, it
is important that values that update independently from one another are kept
in separate contexts because otherwise, unnecessary re-renders are likely to
happen. For example, a reactive value and its respective setter function
should be put in separate contexts because the former can change, while the
latter never changes. To generate contexts like that, please use
createGranularContext.
enum Direction {
Up,
Down,
Left,
Right,
}
// Before:
const DirectionContext = createContext<Direction | undefined>(undefined);
DirectionContext.displayName = 'DirectionContext';
const DirectionProvider = DirectionContext.Provider;
const useDirection = () => {
const direction = useContext(DirectionContext);
if (direction === undefined) {
// Called outside of a <DirectionContext.Provider> boundary!
// Or maybe undefined was explicitly provided as the context value
// (ideally that shouldn't be allowed, but it is because we had to include
// undefined in the context type so as to provide a meaningful default)
throw new Error('No DirectionContext value was provided');
}
// Thanks to the undefined check, the type is now narrowed down to Direction
return direction;
};
// After:
const { DirectionProvider, useDirection } =
createRequiredContext<Direction>()('Direction'); // That's it :)
const Parent = () => (
// Providing undefined as the value is not allowed 👍
<DirectionProvider value={Direction.Up}>
<Child />
</DirectionProvider>
);
const Child = () => `Provided direction: ${Direction[useDirection()]}`;
// Custom provider example:
const { TimeProvider, useTime } = createRequiredContext(
'Time',
({ startTime = 0 }: { startTime?: number }) => {
const [time, setTime] = useState(startTime);
useEffect(() => {
const interval = setInterval(() => setTime((t) => t + 1), 1000);
return () => clearInterval(interval);
}, []);
return time;
},
);
const Parent = () => (
<TimeProvider startTime={-30}>
<Child />
</TimeProvider>
);
const Child = () => `Time: ${useTime()}`;name
A string the context's display name is derived from
providerHook
An optional custom provider hook that receives props passed to the provider component as its argument and should return the context's current value
An object with the following properties:
`${capitalize(name)}Provider`(e.g.DirectionProvider): the provider component`use${capitalize(name)}`(e.g.useDirection): a hook that returns the current context value if one was provided, or throws an error otherwise
CreateRequiredContext,
createGranularContext
function wrapJSX<Children>(children): JSXWrapPipe<Children>;Defined in: misc/wrapJSX.tsx:98
An alternative way to compose JSX that avoids ever-increasing indentation
A more general version of the context-specific contextualize
function.
// Before:
createRoot(document.getElementById('root')!).render(
<StrictMode>
<I18nextProvider i18n={i18n}>
<QueryClientProvider client={queryClient}>
<NuqsAdapter>
<ThemeProvider theme={theme}>
<ToasterProvider>
<App />
</ToasterProvider>
</ThemeProvider>
</NuqsAdapter>
</QueryClientProvider>
</I18nextProvider>
</StrictMode>,
);
// After:
createRoot(document.getElementById('root')!).render(
wrapJSX(<App />)
.with(ToasterProvider)
.with(ThemeProvider, { theme })
.with(NuqsAdapter)
.with(QueryClientProvider, { client: queryClient })
.with(I18nextProvider, { i18n })
.with(StrictMode)
.end(),
);| Type Parameter |
|---|
|
|
| Parameter | Type | Description |
|---|---|---|
|
|
|
The children to wrap |
JSXWrapPipe<Children>
An object with the following properties:
with: a function that accepts a componentComponentand propspropsfor it as arguments and returnswrapJSX(<Component {...props}>{children}</Component>)end: a function that returnschildren
type UseEventListener = UseEventListenerWithImplicitWindowTarget &
UseEventListenerWithExplicitGlobalTarget &
UseEventListenerWithAnyExplicitTarget;Defined in: hooks/useEventListener.ts:13
The type of useEventListener
useEventListener,
UseEventListenerWithImplicitWindowTarget,
UseEventListenerWithExplicitGlobalTarget,
UseEventListenerWithAnyExplicitTarget
type UseEventListenerWithImplicitWindowTarget = <K>(...args) => void;Defined in: hooks/useEventListener.ts:22
| Type Parameter |
|---|
|
|
| Parameter | Type |
|---|---|
|
... |
void
useEventListener,
UseEventListenerWithImplicitWindowTargetArgs
type UseEventListenerWithExplicitGlobalTarget =
UseEventListenerWithExplicitTarget<Window, WindowEventMap> &
UseEventListenerWithExplicitTarget<Document, DocumentEventMap> &
UseEventListenerWithExplicitTarget<HTMLElement, HTMLElementEventMap> &
UseEventListenerWithExplicitTarget<SVGElement, SVGElementEventMap> &
UseEventListenerWithExplicitTarget<MathMLElement, MathMLElementEventMap>;Defined in: hooks/useEventListener.ts:33
useEventListener,
UseEventListenerWithExplicitTarget
type UseEventListenerWithExplicitTarget<Target, EventMap> = <T, K>(
...args
) => void;Defined in: hooks/useEventListener.ts:45
| Type Parameter |
|---|
|
|
|
|
| Type Parameter |
|---|
|
|
|
|
| Parameter | Type |
|---|---|
|
... |
|
void
useEventListener,
UseEventListenerWithExplicitTargetArgs
type UseEventListenerWithAnyExplicitTarget = UseEventListenerWithExplicitTarget<
EventTarget,
Record<string, Event>
>;Defined in: hooks/useEventListener.ts:57
useEventListener,
UseEventListenerWithExplicitTarget
type UseEventListenerWithImplicitWindowTargetArgs<K> =
UseEventListenerWithExplicitTargetArgs<WindowEventMap, Window, K> extends [
unknown,
...infer Args,
]
? Args
: never;Defined in: hooks/useEventListener.ts:65
| Type Parameter |
|---|
|
|
useEventListener,
UseEventListenerWithExplicitTargetArgs
type UseEventListenerWithExplicitTargetArgs<EventMap, T, K> = [
(
| T
| (RefObject<T | null | undefined> & {
addEventListener?: never;
})
| null
| undefined
),
K,
(this, event) => void,
AddEventListenerOptions | boolean | undefined,
];Defined in: hooks/useEventListener.ts:79
| Type Parameter |
|---|
|
|
|
|
|
|
type ContextualizePipe<Children> = {
with: ContextualizeWith;
end: () => Children;
};Defined in: misc/contextualize.tsx:12
The return type of contextualize
contextualize,
ContextualizeWith
| Type Parameter |
|---|
|
|
| Property | Type |
|---|---|
|
() => |
type ContextualizeWith = <T>(
Provider,
value,
) => ContextualizePipe<ReactElement>;Defined in: misc/contextualize.tsx:22
| Type Parameter |
|---|
|
|
| Parameter | Type |
|---|---|
|
|
|
|
|
|
ContextualizePipe<ReactElement>
contextualize,
ContextualizePipe
type CreateRequiredContext = CreateRequiredContextWithStandardProvider &
CreateRequiredContextWithCustomProvider;Defined in: misc/createRequiredContext.tsx:24
The type of createRequiredContext
createRequiredContext,
CreateRequiredContextWithStandardProvider,
CreateRequiredContextWithCustomProvider
type CreateRequiredContextResultHookPart<Name, T> = {
[K in `use${Capitalize<Name>}`]: () => T;
};Defined in: misc/createRequiredContext.tsx:31
| Type Parameter |
|---|
|
|
|
|
type CreateRequiredContextWithStandardProvider = <T>() => <Name>(
name,
) => CreateRequiredContextWithStandardProviderResult<Name, T>;Defined in: misc/createRequiredContext.tsx:40
| Type Parameter | Default type |
|---|---|
|
|
|
<Name>(name) => CreateRequiredContextWithStandardProviderResult<Name, T>
createRequiredContext,
CreateRequiredContextWithStandardProviderResult
type CreateRequiredContextWithStandardProviderResult<Name, T> = {
[K in `${Capitalize<Name>}Provider`]: Provider<T>;
} & CreateRequiredContextResultHookPart<Name, T>;Defined in: misc/createRequiredContext.tsx:51
| Type Parameter |
|---|
|
|
|
|
createRequiredContext,
CreateRequiredContextResultHookPart
type CreateRequiredContextWithCustomProvider = <Name, T, Props>(
...args
) => CreateRequiredContextWithCustomProviderResult<Name, T, Props>;Defined in: misc/createRequiredContext.tsx:64
| Type Parameter | Default type |
|---|---|
|
|
‐ |
|
|
‐ |
|
|
{ } |
| Parameter | Type |
|---|---|
|
... |
|
CreateRequiredContextWithCustomProviderResult<Name, T, Props>
createRequiredContext,
CreateRequiredContextWithCustomProviderArgs,
CreateRequiredContextWithCustomProviderResult
type CreateRequiredContextWithCustomProviderArgs<Name, T, Props> = [
string extends Name ? never : Name,
(props) => T,
];Defined in: misc/createRequiredContext.tsx:77
| Type Parameter |
|---|
|
|
|
|
|
|
type CreateRequiredContextWithCustomProviderResult<Name, T, Props> =
CreateRequiredContextWithCustomProviderResultProviderPart<Name, Props> &
CreateRequiredContextResultHookPart<Name, T>;Defined in: misc/createRequiredContext.tsx:92
| Type Parameter |
|---|
|
|
|
|
|
|
createRequiredContext,
CreateRequiredContextWithCustomProviderResultProviderPart,
CreateRequiredContextResultHookPart
type CreateRequiredContextWithCustomProviderResultProviderPart<Name, Props> = {
[K in `${Capitalize<Name>}Provider`]: FunctionComponent<
Props & { children?: ReactNode }
>;
};Defined in: misc/createRequiredContext.tsx:103
| Type Parameter |
|---|
|
|
|
|
type JSXWrapPipe<Children> = {
with: WrapJSXWith<Children>;
end: () => Children;
};Defined in: misc/wrapJSX.tsx:18
The return type of wrapJSX
| Type Parameter |
|---|
|
|
| Property | Type |
|---|---|
|
|
|
|
() => |
type WrapJSXWith<Children> = <C>(...args) => JSXWrapPipe<ReactElement>;Defined in: misc/wrapJSX.tsx:28
| Type Parameter |
|---|
|
|
| Type Parameter |
|---|
|
|
| Parameter | Type |
|---|---|
|
... |
[ |
JSXWrapPipe<ReactElement>