Skip to content

Commit

Permalink
Merge pull request #4302 from ziongh/main
Browse files Browse the repository at this point in the history
feat: added isMemo to compact to allow compatibility with react-is dependant libraries
  • Loading branch information
marvinhagemeister committed Mar 19, 2024
2 parents e174713 + 94bfe9d commit a784a62
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 7 deletions.
16 changes: 9 additions & 7 deletions compat/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,16 @@ declare namespace React {
) => preact.VNode<any>;
export function isValidElement(element: any): boolean;
export function isFragment(element: any): boolean;
export function isMemo(element: any): boolean;
export function findDOMNode(
component: preact.Component | Element
): Element | null;

export abstract class PureComponent<P = {}, S = {}, SS = any> extends preact.Component<
P,
S
> {
export abstract class PureComponent<
P = {},
S = {},
SS = any
> extends preact.Component<P, S> {
isPureReactComponent: boolean;
}

Expand Down Expand Up @@ -174,9 +176,9 @@ declare namespace React {

export type ComponentPropsWithRef<
C extends ComponentType<any> | keyof JSXInternal.IntrinsicElements
> = C extends (new(props: infer P) => Component<any, any>)
? PropsWithoutRef<P> & RefAttributes<InstanceType<C>>
: ComponentProps<C>;
> = C extends new (props: infer P) => Component<any, any>
? PropsWithoutRef<P> & RefAttributes<InstanceType<C>>
: ComponentProps<C>;

export function flushSync<R>(fn: () => R): R;
export function flushSync<A, R>(fn: (a: A) => R, a: A): R;
Expand Down
17 changes: 17 additions & 0 deletions compat/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ function isFragment(element) {
return isValidElement(element) && element.type === Fragment;
}

/**
* Check if the passed element is a Memo node.
* @param {*} element The element to check
* @returns {boolean}
*/
function isMemo(element) {
return (
!!element &&
!!element.displayName &&
(typeof element.displayName === 'string' ||
element.displayName instanceof String) &&
element.displayName.startsWith('Memo(')
);
}

/**
* Wrap `cloneElement` to abort if the passed element is not a valid element and apply
* all vnode normalizations.
Expand Down Expand Up @@ -215,6 +230,7 @@ export {
Fragment,
isValidElement,
isFragment,
isMemo,
findDOMNode,
Component,
PureComponent,
Expand Down Expand Up @@ -263,6 +279,7 @@ export default {
isValidElement,
isElement,
isFragment,
isMemo,
findDOMNode,
Component,
PureComponent,
Expand Down
37 changes: 37 additions & 0 deletions compat/test/browser/isMemo.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { createElement as preactCreateElement, Fragment } from 'preact';
import React, { createElement, isMemo, memo } from 'preact/compat';

describe('isMemo', () => {
it('should check return false for invalid arguments', () => {
expect(isMemo(null)).to.equal(false);
expect(isMemo(false)).to.equal(false);
expect(isMemo(true)).to.equal(false);
expect(isMemo('foo')).to.equal(false);
expect(isMemo(123)).to.equal(false);
expect(isMemo([])).to.equal(false);
expect(isMemo({})).to.equal(false);
});

it('should detect a preact memo', () => {
function Foo() {
return <h1>Hello World</h1>;
}
let App = memo(Foo);
expect(isMemo(App)).to.equal(true);
});

it('should not detect a normal element', () => {
function Foo() {
return <h1>Hello World</h1>;
}
expect(isMemo(Foo)).to.equal(false);
});

it('should detect a preact vnode as false', () => {
expect(isMemo(preactCreateElement(Fragment, {}))).to.equal(false);
});

it('should detect a compat vnode as false', () => {
expect(isMemo(React.createElement(Fragment, {}))).to.equal(false);
});
});

0 comments on commit a784a62

Please sign in to comment.