diff --git a/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx b/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx
index 4f057015a..164664466 100644
--- a/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx
+++ b/packages/nextjs/components/scaffold-eth/Input/AddressInput.tsx
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from "react";
import { blo } from "blo";
-import { useDebounce } from "usehooks-ts";
+import { useDebounceValue } from "usehooks-ts";
import { Address, isAddress } from "viem";
import { useEnsAddress, useEnsAvatar, useEnsName } from "wagmi";
import { CommonInputProps, InputBase, isENS } from "~~/components/scaffold-eth";
@@ -11,29 +11,39 @@ import { CommonInputProps, InputBase, isENS } from "~~/components/scaffold-eth";
export const AddressInput = ({ value, name, placeholder, onChange, disabled }: CommonInputProps
) => {
// Debounce the input to keep clean RPC calls when resolving ENS names
// If the input is an address, we don't need to debounce it
- const _debouncedValue = useDebounce(value, 500);
+ const [_debouncedValue] = useDebounceValue(value, 500);
const debouncedValue = isAddress(value) ? value : _debouncedValue;
const isDebouncedValueLive = debouncedValue === value;
// If the user changes the input after an ENS name is already resolved, we want to remove the stale result
const settledValue = isDebouncedValueLive ? debouncedValue : undefined;
- const { data: ensAddress, isLoading: isEnsAddressLoading } = useEnsAddress({
+ const {
+ data: ensAddress,
+ isLoading: isEnsAddressLoading,
+ isError: isEnsAddressError,
+ isSuccess: isEnsAddressSuccess,
+ } = useEnsAddress({
name: settledValue,
- enabled: isENS(debouncedValue),
+ enabled: isDebouncedValueLive && isENS(debouncedValue),
chainId: 1,
cacheTime: 30_000,
});
const [enteredEnsName, setEnteredEnsName] = useState();
- const { data: ensName, isLoading: isEnsNameLoading } = useEnsName({
+ const {
+ data: ensName,
+ isLoading: isEnsNameLoading,
+ isError: isEnsNameError,
+ isSuccess: isEnsNameSuccess,
+ } = useEnsName({
address: settledValue as Address,
enabled: isAddress(debouncedValue),
chainId: 1,
cacheTime: 30_000,
});
- const { data: ensAvatar } = useEnsAvatar({
+ const { data: ensAvatar, isLoading: isEnsAvtarLoading } = useEnsAvatar({
name: ensName,
enabled: Boolean(ensName),
chainId: 1,
@@ -57,6 +67,14 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
[onChange],
);
+ const reFocus =
+ isEnsAddressError ||
+ isEnsNameError ||
+ isEnsNameSuccess ||
+ isEnsAddressSuccess ||
+ ensName === null ||
+ ensAddress === null;
+
return (
name={name}
@@ -65,9 +83,11 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
value={value as Address}
onChange={handleChange}
disabled={isEnsAddressLoading || isEnsNameLoading || disabled}
+ reFocus={reFocus}
prefix={
- ensName && (
+ ensName ? (
+ {isEnsAvtarLoading &&
}
{ensAvatar ? (
{
@@ -78,6 +98,13 @@ export const AddressInput = ({ value, name, placeholder, onChange, disabled }: C
) : null}
{enteredEnsName ?? ensName}
+ ) : (
+ (isEnsNameLoading || isEnsAddressLoading) && (
+
+ )
)
}
suffix={
diff --git a/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx b/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx
index 73d5a4f8a..f38bca217 100644
--- a/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx
+++ b/packages/nextjs/components/scaffold-eth/Input/InputBase.tsx
@@ -1,10 +1,11 @@
-import { ChangeEvent, ReactNode, useCallback } from "react";
+import { ChangeEvent, FocusEvent, ReactNode, useCallback, useEffect, useRef } from "react";
import { CommonInputProps } from "~~/components/scaffold-eth";
type InputBaseProps = CommonInputProps & {
error?: boolean;
prefix?: ReactNode;
suffix?: ReactNode;
+ reFocus?: boolean;
};
export const InputBase = string } | undefined = string>({
@@ -16,7 +17,10 @@ export const InputBase = string } | undefined = str
disabled,
prefix,
suffix,
+ reFocus,
}: InputBaseProps) => {
+ const inputReft = useRef(null);
+
let modifier = "";
if (error) {
modifier = "border-error";
@@ -31,6 +35,17 @@ export const InputBase = string } | undefined = str
[onChange],
);
+ // Runs only when reFocus prop is passed, usefull for setting the cursor
+ // at the end of the input. Example AddressInput
+ const onFocus = (e: FocusEvent) => {
+ if (reFocus !== undefined) {
+ e.currentTarget.setSelectionRange(e.currentTarget.value.length, e.currentTarget.value.length);
+ }
+ };
+ useEffect(() => {
+ if (reFocus !== undefined && reFocus === true) inputReft.current?.focus();
+ }, [reFocus]);
+
return (
{prefix}
@@ -42,6 +57,8 @@ export const InputBase = string } | undefined = str
onChange={handleChange}
disabled={disabled}
autoComplete="off"
+ ref={inputReft}
+ onFocus={onFocus}
/>
{suffix}