From 8b0919ca651f5a2fcef347ff5a61ab43e703c269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mih=C3=A1ly=20Lengyel?= Date: Mon, 13 May 2024 22:21:27 +0200 Subject: [PATCH] fix: inputComponents now get stable callbacks (#819) --- CHANGELOG.md | 6 ++++ examples/for-tests/src/App.js | 32 ++++++++++++------- lib/build/components/assets/blockedIcon.d.ts | 3 +- lib/build/components/assets/otpEmailIcon.d.ts | 3 +- lib/build/components/assets/otpSMSIcon.d.ts | 3 +- lib/build/components/assets/totpIcon.d.ts | 3 +- lib/build/emailpassword-shared9.js | 6 ++-- lib/build/genericComponentOverrideContext.js | 2 +- .../components/library/formRow.d.ts | 5 +-- .../dynamicLoginMethodsSpinner/index.d.ts | 5 ++- .../themes/linkClickedScreen/index.d.ts | 3 +- .../themes/signInUp/phoneNumberInput.d.ts | 2 +- lib/build/recipe/passwordless/recipe.d.ts | 5 +-- .../components/library/providerButton.d.ts | 6 +--- .../themes/signInAndUpCallback/index.d.ts | 5 ++- lib/build/recipe/thirdparty/prebuiltui.d.ts | 2 +- .../thirdpartyemailpassword/prebuiltui.d.ts | 2 +- .../components/themes/signInUp/index.d.ts | 5 ++- lib/build/recipe/totp/recipe.d.ts | 3 +- lib/build/version.d.ts | 2 +- .../components/library/formBase.tsx | 6 ++-- lib/ts/version.ts | 2 +- package-lock.json | 4 +-- package.json | 2 +- 24 files changed, 65 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48862fe03..fa44ca008 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [unreleased] +## [0.41.1] - 2024-05-13 + +### Fixes + +- Custom `inputComponents` (in sign in/up form fields) now get reference-stable callbacks. + ## [0.41.0] - 2024-05-09 ### Breaking changes diff --git a/examples/for-tests/src/App.js b/examples/for-tests/src/App.js index e189c5862..9b28b6d16 100644 --- a/examples/for-tests/src/App.js +++ b/examples/for-tests/src/App.js @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import "./App.css"; import AppWithoutRouter from "./AppWithoutRouter"; @@ -289,21 +289,31 @@ const incorrectFormFields = [ }, ]; +const DropdownInputComponent = ({ value, name, onChange }) => { + const onChangeRef = useRef(onChange); + + if (onChangeRef.current !== onChange) { + throw new Error("callbacks passed to inputComponents should be reference stable"); + } + + return ( + + ); +}; + const customFields = [ { id: "select-dropdown", label: "Select Dropdown", nonOptionalErrorMsg: "Select dropdown is not an optional", - inputComponent: ({ value, name, onChange }) => ( - - ), + inputComponent: DropdownInputComponent, optional: true, }, { diff --git a/lib/build/components/assets/blockedIcon.d.ts b/lib/build/components/assets/blockedIcon.d.ts index 36a055cab..1832c8417 100644 --- a/lib/build/components/assets/blockedIcon.d.ts +++ b/lib/build/components/assets/blockedIcon.d.ts @@ -1 +1,2 @@ -export declare const BlockedIcon: () => import("react/jsx-runtime").JSX.Element; +/// +export declare const BlockedIcon: () => JSX.Element; diff --git a/lib/build/components/assets/otpEmailIcon.d.ts b/lib/build/components/assets/otpEmailIcon.d.ts index f1424c14b..1de53f103 100644 --- a/lib/build/components/assets/otpEmailIcon.d.ts +++ b/lib/build/components/assets/otpEmailIcon.d.ts @@ -1 +1,2 @@ -export declare const OTPEmailIcon: () => import("react/jsx-runtime").JSX.Element; +/// +export declare const OTPEmailIcon: () => JSX.Element; diff --git a/lib/build/components/assets/otpSMSIcon.d.ts b/lib/build/components/assets/otpSMSIcon.d.ts index cb6600f53..5e409d35a 100644 --- a/lib/build/components/assets/otpSMSIcon.d.ts +++ b/lib/build/components/assets/otpSMSIcon.d.ts @@ -1 +1,2 @@ -export declare const OTPSMSIcon: () => import("react/jsx-runtime").JSX.Element; +/// +export declare const OTPSMSIcon: () => JSX.Element; diff --git a/lib/build/components/assets/totpIcon.d.ts b/lib/build/components/assets/totpIcon.d.ts index 091d00d00..8f2bba229 100644 --- a/lib/build/components/assets/totpIcon.d.ts +++ b/lib/build/components/assets/totpIcon.d.ts @@ -1 +1,2 @@ -export declare const TOTPIcon: () => import("react/jsx-runtime").JSX.Element; +/// +export declare const TOTPIcon: () => JSX.Element; diff --git a/lib/build/emailpassword-shared9.js b/lib/build/emailpassword-shared9.js index 332ecdaea..dd97bee95 100644 --- a/lib/build/emailpassword-shared9.js +++ b/lib/build/emailpassword-shared9.js @@ -455,7 +455,7 @@ function InputComponentWrapper(props) { value: value, }); }, - [onInputFocus, field] + [onInputFocus, field.id] ); var useCallbackOnInputBlur = React.useCallback( function (value) { @@ -464,7 +464,7 @@ function InputComponentWrapper(props) { value: value, }); }, - [onInputBlur, field] + [onInputBlur, field.id] ); var useCallbackOnInputChange = React.useCallback( function (value) { @@ -473,7 +473,7 @@ function InputComponentWrapper(props) { value: value, }); }, - [onInputChange, field] + [onInputChange, field.id] ); return field.inputComponent !== undefined ? jsxRuntime.jsx(field.inputComponent, { diff --git a/lib/build/genericComponentOverrideContext.js b/lib/build/genericComponentOverrideContext.js index 13c41d2cc..9e0f94c98 100644 --- a/lib/build/genericComponentOverrideContext.js +++ b/lib/build/genericComponentOverrideContext.js @@ -265,7 +265,7 @@ var SSR_ERROR = * License for the specific language governing permissions and limitations * under the License. */ -var package_version = "0.41.0"; +var package_version = "0.41.1"; /* Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved. * diff --git a/lib/build/recipe/emailpassword/components/library/formRow.d.ts b/lib/build/recipe/emailpassword/components/library/formRow.d.ts index 6ce275da7..16521d4ad 100644 --- a/lib/build/recipe/emailpassword/components/library/formRow.d.ts +++ b/lib/build/recipe/emailpassword/components/library/formRow.d.ts @@ -2,8 +2,5 @@ import type { PropsWithChildren } from "react"; declare type FormRowProps = { hasError?: boolean; }; -export default function FormRow({ - children, - hasError, -}: PropsWithChildren): import("react/jsx-runtime").JSX.Element; +export default function FormRow({ children, hasError }: PropsWithChildren): JSX.Element; export {}; diff --git a/lib/build/recipe/multitenancy/components/themes/dynamicLoginMethodsSpinner/index.d.ts b/lib/build/recipe/multitenancy/components/themes/dynamicLoginMethodsSpinner/index.d.ts index 12fa33fbb..2998db3b7 100644 --- a/lib/build/recipe/multitenancy/components/themes/dynamicLoginMethodsSpinner/index.d.ts +++ b/lib/build/recipe/multitenancy/components/themes/dynamicLoginMethodsSpinner/index.d.ts @@ -1,4 +1,3 @@ +/// import type { NormalisedConfig } from "../../../types"; -export declare const DynamicLoginMethodsSpinnerTheme: (props: { - config: NormalisedConfig; -}) => import("react/jsx-runtime").JSX.Element; +export declare const DynamicLoginMethodsSpinnerTheme: (props: { config: NormalisedConfig }) => JSX.Element; diff --git a/lib/build/recipe/passwordless/components/themes/linkClickedScreen/index.d.ts b/lib/build/recipe/passwordless/components/themes/linkClickedScreen/index.d.ts index 090465980..b81206107 100644 --- a/lib/build/recipe/passwordless/components/themes/linkClickedScreen/index.d.ts +++ b/lib/build/recipe/passwordless/components/themes/linkClickedScreen/index.d.ts @@ -1,2 +1,3 @@ +/// import type { LinkClickedScreenProps } from "../../../types"; -export declare const LinkClickedScreen: (props: LinkClickedScreenProps) => import("react/jsx-runtime").JSX.Element; +export declare const LinkClickedScreen: (props: LinkClickedScreenProps) => JSX.Element; diff --git a/lib/build/recipe/passwordless/components/themes/signInUp/phoneNumberInput.d.ts b/lib/build/recipe/passwordless/components/themes/signInUp/phoneNumberInput.d.ts index 8a40578be..23021e2fd 100644 --- a/lib/build/recipe/passwordless/components/themes/signInUp/phoneNumberInput.d.ts +++ b/lib/build/recipe/passwordless/components/themes/signInUp/phoneNumberInput.d.ts @@ -17,4 +17,4 @@ declare function PhoneNumberInput({ export default PhoneNumberInput; export declare const phoneNumberInputWithInjectedProps: ( injectedProps: Partial -) => (props: any) => import("react/jsx-runtime").JSX.Element; +) => (props: any) => JSX.Element; diff --git a/lib/build/recipe/passwordless/recipe.d.ts b/lib/build/recipe/passwordless/recipe.d.ts index 46c112da2..1fad76ad5 100644 --- a/lib/build/recipe/passwordless/recipe.d.ts +++ b/lib/build/recipe/passwordless/recipe.d.ts @@ -1,3 +1,4 @@ +/// import PasswordlessWebJS from "supertokens-web-js/recipe/passwordless"; import AuthRecipe from "../authRecipe"; import type { @@ -13,14 +14,14 @@ export declare const otpPhoneFactor: { name: string; description: string; path: string; - logo: () => import("react/jsx-runtime").JSX.Element; + logo: () => JSX.Element; }; export declare const otpEmailFactor: { id: string; name: string; description: string; path: string; - logo: () => import("react/jsx-runtime").JSX.Element; + logo: () => JSX.Element; }; export declare const passwordlessFirstFactors: readonly [string, string, string, string]; export default class Passwordless extends AuthRecipe< diff --git a/lib/build/recipe/thirdparty/components/library/providerButton.d.ts b/lib/build/recipe/thirdparty/components/library/providerButton.d.ts index ead01b079..33eb55a42 100644 --- a/lib/build/recipe/thirdparty/components/library/providerButton.d.ts +++ b/lib/build/recipe/thirdparty/components/library/providerButton.d.ts @@ -4,8 +4,4 @@ export declare type ProviderButtonProps = { displayName: string; logo?: JSX.Element; }; -export default function ProviderButton({ - logo, - providerName, - displayName, -}: ProviderButtonProps): import("react/jsx-runtime").JSX.Element; +export default function ProviderButton({ logo, providerName, displayName }: ProviderButtonProps): JSX.Element; diff --git a/lib/build/recipe/thirdparty/components/themes/signInAndUpCallback/index.d.ts b/lib/build/recipe/thirdparty/components/themes/signInAndUpCallback/index.d.ts index 8945aff1a..96ebf1db4 100644 --- a/lib/build/recipe/thirdparty/components/themes/signInAndUpCallback/index.d.ts +++ b/lib/build/recipe/thirdparty/components/themes/signInAndUpCallback/index.d.ts @@ -1,4 +1,3 @@ +/// import type { NormalisedConfig } from "../../../types"; -export declare const SignInAndUpCallbackTheme: (props: { - config: NormalisedConfig; -}) => import("react/jsx-runtime").JSX.Element; +export declare const SignInAndUpCallbackTheme: (props: { config: NormalisedConfig }) => JSX.Element; diff --git a/lib/build/recipe/thirdparty/prebuiltui.d.ts b/lib/build/recipe/thirdparty/prebuiltui.d.ts index 6beeb7748..adfd192bf 100644 --- a/lib/build/recipe/thirdparty/prebuiltui.d.ts +++ b/lib/build/recipe/thirdparty/prebuiltui.d.ts @@ -46,7 +46,7 @@ export declare class ThirdPartyPreBuiltUI extends RecipeRouter { userContext?: UserContext | undefined; } >; - static SignInAndUpCallbackTheme: (props: { config: NormalisedConfig }) => import("react/jsx-runtime").JSX.Element; + static SignInAndUpCallbackTheme: (props: { config: NormalisedConfig }) => JSX.Element; } declare const SignInAndUp: ( prop?: FeatureBaseProps<{ diff --git a/lib/build/recipe/thirdpartyemailpassword/prebuiltui.d.ts b/lib/build/recipe/thirdpartyemailpassword/prebuiltui.d.ts index 91d1accf7..7c71c7db3 100644 --- a/lib/build/recipe/thirdpartyemailpassword/prebuiltui.d.ts +++ b/lib/build/recipe/thirdpartyemailpassword/prebuiltui.d.ts @@ -50,7 +50,7 @@ export declare class ThirdPartyEmailPasswordPreBuiltUI extends RecipeRouter { ) => JSX.Element; static ThirdPartySignInAndUpCallbackTheme: (props: { config: import("../thirdparty/types").NormalisedConfig; - }) => import("react/jsx-runtime").JSX.Element; + }) => JSX.Element; static ResetPasswordUsingTokenTheme: typeof ResetPasswordUsingTokenTheme; static SignInAndUpTheme: typeof SignInAndUpTheme; } diff --git a/lib/build/recipe/thirdpartypasswordless/components/themes/signInUp/index.d.ts b/lib/build/recipe/thirdpartypasswordless/components/themes/signInUp/index.d.ts index 184038689..7c7649bfe 100644 --- a/lib/build/recipe/thirdpartypasswordless/components/themes/signInUp/index.d.ts +++ b/lib/build/recipe/thirdpartypasswordless/components/themes/signInUp/index.d.ts @@ -1,5 +1,4 @@ +/// import type { ThirdPartyPasswordlessSignInAndUpThemeProps } from "../../../types"; -declare function SignInUpThemeWrapper( - props: ThirdPartyPasswordlessSignInAndUpThemeProps -): import("react/jsx-runtime").JSX.Element; +declare function SignInUpThemeWrapper(props: ThirdPartyPasswordlessSignInAndUpThemeProps): JSX.Element; export default SignInUpThemeWrapper; diff --git a/lib/build/recipe/totp/recipe.d.ts b/lib/build/recipe/totp/recipe.d.ts index 9f75f2a9e..e4f837463 100644 --- a/lib/build/recipe/totp/recipe.d.ts +++ b/lib/build/recipe/totp/recipe.d.ts @@ -1,3 +1,4 @@ +/// import TOTPWebJS from "supertokens-web-js/recipe/totp"; import RecipeModule from "../recipeModule"; import type { @@ -13,7 +14,7 @@ export declare const totpFactor: { name: string; description: string; path: string; - logo: () => import("react/jsx-runtime").JSX.Element; + logo: () => JSX.Element; }; export default class TOTP extends RecipeModule< GetRedirectionURLContext, diff --git a/lib/build/version.d.ts b/lib/build/version.d.ts index a86c4904e..d1f3c4287 100644 --- a/lib/build/version.d.ts +++ b/lib/build/version.d.ts @@ -1 +1 @@ -export declare const package_version = "0.41.0"; +export declare const package_version = "0.41.1"; diff --git a/lib/ts/recipe/emailpassword/components/library/formBase.tsx b/lib/ts/recipe/emailpassword/components/library/formBase.tsx index 3d44f9832..e045a176b 100644 --- a/lib/ts/recipe/emailpassword/components/library/formBase.tsx +++ b/lib/ts/recipe/emailpassword/components/library/formBase.tsx @@ -66,7 +66,7 @@ function InputComponentWrapper(props: { value, }); }, - [onInputFocus, field] + [onInputFocus, field.id] ); const useCallbackOnInputBlur = useCallback<(value: string) => void>( @@ -76,7 +76,7 @@ function InputComponentWrapper(props: { value, }); }, - [onInputBlur, field] + [onInputBlur, field.id] ); const useCallbackOnInputChange = useCallback( @@ -86,7 +86,7 @@ function InputComponentWrapper(props: { value, }); }, - [onInputChange, field] + [onInputChange, field.id] ); return field.inputComponent !== undefined ? ( diff --git a/lib/ts/version.ts b/lib/ts/version.ts index 1cb8c116b..18bbee7e8 100644 --- a/lib/ts/version.ts +++ b/lib/ts/version.ts @@ -12,4 +12,4 @@ * License for the specific language governing permissions and limitations * under the License. */ -export const package_version = "0.41.0"; +export const package_version = "0.41.1"; diff --git a/package-lock.json b/package-lock.json index 57bc0a7b7..66e4beb78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "supertokens-auth-react", - "version": "0.41.0", + "version": "0.41.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "supertokens-auth-react", - "version": "0.41.0", + "version": "0.41.1", "license": "Apache-2.0", "dependencies": { "intl-tel-input": "^17.0.19", diff --git a/package.json b/package.json index b4b183a6e..447db5352 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "supertokens-auth-react", - "version": "0.41.0", + "version": "0.41.1", "description": "ReactJS SDK that provides login functionality with SuperTokens.", "main": "./index.js", "engines": {