@winglet/react-utils
Version:
React utility library providing custom hooks, higher-order components (HOCs), and utility functions to enhance React application development with improved reusability and functionality
88 lines (87 loc) • 3.18 kB
TypeScript
import type { ComponentType, MemoExoticComponent } from 'react';
/**
* Determines whether a given value is a React component wrapped with React.memo().
*
* Identifies memoized components by inspecting the internal React symbol type
* `$$typeof`, which is set to `Symbol.for('react.memo')` for components that
* have been enhanced with React.memo() for performance optimization.
*
* @typeParam Props - The component props type (defaults to any)
* @typeParam Component - The specific memoized component type
* @param component - The value to inspect for memoized component characteristics
* @returns Type-safe boolean indicating whether the value is a memoized component
*
* @example
* Basic memoized component detection:
* ```typescript
* import React, { memo, Component } from 'react';
* import { isMemoComponent } from '@winglet/react-utils';
*
* // Function component
* const BasicComponent = () => <div>Hello World</div>;
*
* // Memoized function component
* const MemoizedComponent = memo(BasicComponent);
*
* // Class component
* class ClassComponent extends Component {
* render() { return <div>Hello World</div>; }
* }
*
* // Memoized class component
* const MemoizedClassComponent = memo(ClassComponent);
*
* console.log(isMemoComponent(BasicComponent)); // false
* console.log(isMemoComponent(MemoizedComponent)); // true
* console.log(isMemoComponent(ClassComponent)); // false
* console.log(isMemoComponent(MemoizedClassComponent)); // true
* ```
*
* @example
* With custom comparison function:
* ```typescript
* interface Props {
* name: string;
* age: number;
* }
*
* const PersonComponent = ({ name, age }: Props) => (
* <div>{name} is {age} years old</div>
* );
*
* const MemoizedPerson = memo(PersonComponent, (prevProps, nextProps) => {
* return prevProps.name === nextProps.name && prevProps.age === nextProps.age;
* });
*
* console.log(isMemoComponent(MemoizedPerson)); // true
* ```
*
* @example
* TypeScript type inference:
* ```typescript
* interface ComponentProps {
* title: string;
* }
*
* if (isMemoComponent<ComponentProps>(someComponent)) {
* // TypeScript knows someComponent is MemoExoticComponent<ComponentType<ComponentProps>>
* const displayName = someComponent.displayName;
* const type = someComponent.type; // The wrapped component
* }
* ```
*
* @remarks
* This function identifies memoized components by:
* - Verifying the value is a non-null object
* - Checking for the `$$typeof` property equal to `Symbol.for('react.memo')`
*
* Memoized components are objects with special properties:
* - `type`: The original component that was wrapped
* - `compare`: The comparison function (if provided)
* - `$$typeof`: The React internal symbol identifier
*
* Note that this will return `true` only for components explicitly wrapped
* with `React.memo()`, regardless of whether they were originally functional
* or class components.
*/
export declare const isMemoComponent: <Props extends object = any, Component extends MemoExoticComponent<ComponentType<Props>> = MemoExoticComponent<ComponentType<Props>>>(component: unknown) => component is Component;