Custom React Hooks
Relevant source files
The following files were used as context for generating this wiki page:The Quant project utilizes several custom React hooks to encapsulate and reuse stateful logic across components. These hooks primarily focus on advanced ref management and UI state, such as theme handling. They promote cleaner component code, separation of concerns, and provide robust, reusable solutions for common frontend challenges.
The main custom hooks identified are centered around managing React refs, enabling capabilities like composing multiple refs together or ensuring a ref's value is always up-to-date with the latest props. Additionally, while the source for useTheme is not directly provided, its implementation pattern for managing the application's light/dark theme is visible within the Header component.
Summary of Hooks
| Hook | File | Description |
|---|---|---|
useAsRef | src/hooks/use-as-ref.ts | Creates a ref whose .current property is always kept in sync with the latest value of a given prop. |
useComposedRefs | src/lib/compose-refs.ts | Composes multiple refs (callback refs or RefObjects) into a single RefCallback. |
| Theme Logic | src/components/Header.tsx | Implements the logic for toggling between light and dark themes and persisting the choice in localStorage. |
Sources: src/hooks/use-as-ref.ts, src/lib/compose-refs.ts, src/components/Header.tsx
Ref Management Hooks
The project includes specialized hooks for advanced ref handling, which are crucial for building flexible and reusable components.
useAsRef
The useAsRef hook is a utility designed to bridge the gap between props and refs. It takes a value (typically a prop) and returns a ref object. The hook ensures that the ref.current property is updated with the latest value of the prop on every render, using useIsomorphicLayoutEffect to handle both server-side and client-side rendering environments safely. This is useful when an event handler or an effect needs access to the latest value of a prop without being re-created every time the prop changes.
Sources: src/hooks/use-as-ref.ts:5-15
Logic Flow
The diagram below illustrates the execution flow of the useAsRef hook.
Sources: src/hooks/use-as-ref.ts:7-13
Implementation
// src/hooks/use-as-ref.ts
import * as React from "react";
import { useIsomorphicLayoutEffect } from "@/hooks/use-isomorphic-layout-effect";
function useAsRef<T>(props: T) {
const ref = React.useRef<T>(props);
useIsomorphicLayoutEffect(() => {
ref.current = props;
});
return ref;
}
export {
useAsRef
};
Sources: src/hooks/use-as-ref.ts
useComposedRefs
The useComposedRefs hook provides a way to merge multiple refs into a single ref callback. This is particularly useful when a component needs to attach both a local ref and a forwarded ref to a single DOM element. It leverages a helper function, composeRefs, to iterate through an array of refs and assign the DOM node to each one. It correctly handles both RefObjects (created by useRef) and callback refs.
Sources: src/lib/compose-refs.ts:18-39, src/lib/compose-refs.ts:45-48
Logic Flow
This diagram shows how composeRefs assigns a node to multiple refs.
Sources: src/lib/compose-refs.ts:18-39
Implementation
The hook is a lightweight wrapper around the composeRefs utility function, memoizing the result with React.useCallback.
// src/lib/compose-refs.ts
/**
* A utility to compose multiple refs together
* Accepts callback refs and RefObject(s)
*/
function composeRefs<T>(...refs: Array<PossibleRef<T>>): React.RefCallback<T> {
return (node) => {
// ... implementation details ...
refs.map((ref) => {
setRef(ref, node);
// ...
});
// ...
};
}
/**
* A custom hook that composes multiple refs
* Accepts callback refs and RefObject(s)
*/
function useComposedRefs<T>(...refs: Array<PossibleRef<T>>): React.RefCallback<T> {
// biome-ignore lint/correctness/useExhaustiveDependencies: we want to memoize by all values
return React.useCallback(composeRefs(...refs), refs);
}
Sources: src/lib/compose-refs.ts:18-21, src/lib/compose-refs.ts:45-48
UI State Management
Theme Management Logic
While a dedicated useTheme hook is imported in CVSSGenericCalculator.tsx, its source code is not available in the provided context. However, the Header.tsx component contains a complete implementation of the theme-switching functionality, which serves as a reference for how theme state is managed in the application.
This logic handles:
- Initial Theme Detection: On component mount, it checks
localStoragefor a saved theme. If none is found, it respects the user's OS-level preference viawindow.matchMedia('(prefers-color-scheme: dark)'). - State Management: It uses a
useStatehook to keep track of the current theme (lightordark). - Theme Toggling: The
toggleThemefunction switches the theme, updates the component's state, saves the new preference tolocalStorage, and toggles thedarkclass on the<html>element to apply the corresponding CSS styles.
Sources: src/components/Header.tsx:43-61, src/components/CVSSGenericCalculator.tsx:300
Sequence Diagram
The following diagram illustrates the flow of events when a user toggles the theme.
Sources: src/components/Header.tsx:55-60