From d1c2a4284a3944fb4cabc5a377fa87e67bd63613 Mon Sep 17 00:00:00 2001 From: Henry Dineen Date: Tue, 17 Dec 2024 01:08:37 -0500 Subject: [PATCH] Update withErrorBoundary types for forwards compat --- package.json | 2 +- pnpm-lock.yaml | 33 ++++++++++++++++++++------------- src/withErrorBoundary.test.tsx | 24 +++++++++++++++++++++++- src/withErrorBoundary.ts | 24 +++++++++++++----------- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 2fe7adc..db019b5 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "@preconstruct/cli": "^2.8.1", "@types/assert": "^1.5.10", "@types/jest": "^26.0.15", - "@types/react": "^18", + "@types/react": "^18.3.17", "@types/react-dom": "^18", "@typescript-eslint/eslint-plugin": "^5.52.0", "assert": "^2.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70fb59f..85b80ab 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,8 +28,8 @@ importers: specifier: ^26.0.15 version: 26.0.24 '@types/react': - specifier: ^18 - version: 18.2.14 + specifier: ^18.3.17 + version: 18.3.17 '@types/react-dom': specifier: ^18 version: 18.2.6 @@ -961,15 +961,12 @@ packages: '@types/react-dom@18.2.6': resolution: {integrity: sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==} - '@types/react@18.2.14': - resolution: {integrity: sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==} + '@types/react@18.3.17': + resolution: {integrity: sha512-opAQ5no6LqJNo9TqnxBKsgnkIYHozW9KSTlFVoSUJYh1Fl/sswkEoqIugRSm7tbh6pABtYjGAjW+GOS23j8qbw==} '@types/resolve@1.17.1': resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} - '@types/scheduler@0.16.3': - resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} - '@types/semver@7.5.0': resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} @@ -1378,6 +1375,15 @@ packages: supports-color: optional: true + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} @@ -4445,20 +4451,17 @@ snapshots: '@types/react-dom@18.2.6': dependencies: - '@types/react': 18.2.14 + '@types/react': 18.3.17 - '@types/react@18.2.14': + '@types/react@18.3.17': dependencies: '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.3 csstype: 3.1.2 '@types/resolve@1.17.1': dependencies: '@types/node': 20.3.3 - '@types/scheduler@0.16.3': {} - '@types/semver@7.5.0': {} '@types/stack-utils@2.0.1': {} @@ -4499,7 +4502,7 @@ snapshots: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.1.6) - debug: 4.3.4 + debug: 4.4.0 eslint: 8.47.0 optionalDependencies: typescript: 5.1.6 @@ -4919,6 +4922,10 @@ snapshots: dependencies: ms: 2.1.2 + debug@4.4.0: + dependencies: + ms: 2.1.3 + decamelize-keys@1.1.1: dependencies: decamelize: 1.2.0 diff --git a/src/withErrorBoundary.test.tsx b/src/withErrorBoundary.test.tsx index 1ff1186..3c88bb7 100644 --- a/src/withErrorBoundary.test.tsx +++ b/src/withErrorBoundary.test.tsx @@ -2,7 +2,7 @@ * @jest-environment jsdom */ -import { Component, createRef, PropsWithChildren } from "react"; +import { Component, createRef, forwardRef, PropsWithChildren } from "react"; import { createRoot } from "react-dom/client"; import { act } from "react-dom/test-utils"; import { withErrorBoundary } from "./withErrorBoundary"; @@ -81,4 +81,26 @@ describe("withErrorBoundary", () => { expect(ref.current).not.toBeNull(); expect(typeof ref.current?.test).toBe("function"); }); + + it("should forward dom refs", () => { + type Props = { foo: string }; + + const Div = forwardRef((props, ref) => { + return
{props.foo}
; + }); + Div.displayName = "Div"; + + const Wrapped = withErrorBoundary(Div, { + fallback:
Error
, + }); + + const ref = createRef(); + + act(() => { + root.render(); + }); + + expect(ref.current).not.toBeNull(); + expect(ref.current).toBeInstanceOf(HTMLDivElement); + }); }); diff --git a/src/withErrorBoundary.ts b/src/withErrorBoundary.ts index 9c6df97..5b62576 100644 --- a/src/withErrorBoundary.ts +++ b/src/withErrorBoundary.ts @@ -1,26 +1,28 @@ import { createElement, forwardRef, - ForwardedRef, RefAttributes, ForwardRefExoticComponent, PropsWithoutRef, ComponentType, + ComponentRef, + ComponentProps, } from "react"; import { ErrorBoundary } from "./ErrorBoundary"; import { ErrorBoundaryProps } from "./types"; -export function withErrorBoundary( - component: ComponentType, +export function withErrorBoundary>( + component: T, errorBoundaryProps: ErrorBoundaryProps -): ForwardRefExoticComponent & RefAttributes> { - const Wrapped = forwardRef, Props>( - (props: Props, ref: ForwardedRef>) => - createElement( - ErrorBoundary, - errorBoundaryProps, - createElement(component, { ...props, ref }) - ) +): ForwardRefExoticComponent< + PropsWithoutRef> & RefAttributes> +> { + const Wrapped = forwardRef, ComponentProps>((props, ref) => + createElement( + ErrorBoundary, + errorBoundaryProps, + createElement(component, { ...props, ref }) + ) ); // Format for display in DevTools