Typing Error when I pass ref to tw component
theaungmyatmoe opened this issue · 0 comments
theaungmyatmoe commented
Error is occurred when I am building next .
web:build: cache miss, executing 1a17b82bd68f9942
web:build:
web:build: > web@0.0.0 build /home/amm834/workspace/component-lib/apps/web
web:build: > next build
web:build:
web:build: info - Linting and checking validity of types...
web:build: Failed to compile.
web:build:
web:build: ../../packages/ui/components/field/Input.tsx:16:9
web:build: Type error: No overload matches this call.
web:build: Overload 2 of 2, '(props: TailwindComponentPropsWith$As<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, IStyledInputProps, "input", Pick<...> & { ...; }>): ReactElement<...>', gave the following error.
web:build: Type 'ForwardedRef<HTMLLabelElement>' is not assignable to type '((string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement>) & RefObject<HTMLInputElement> & (((instance: HTMLInputElement | null) => void) | RefObject<...>)) | null | undefined'.
web:build: Type '(instance: HTMLLabelElement | null) => void' is not assignable to type '((string | ((instance: HTMLInputElement | null) => void) | RefObject<HTMLInputElement>) & RefObject<HTMLInputElement> & (((instance: HTMLInputElement | null) => void) | RefObject<...>)) | null | undefined'.
web:build: Type '(instance: HTMLLabelElement | null) => void' is not assignable to type '((instance: HTMLInputElement | null) => void) & RefObject<HTMLInputElement>'.
web:build:
web:build: 14 | <StyledInput
web:build: 15 | $as="input"
web:build: > 16 | ref={ref}
web:build: | ^
web:build: 17 | id={id}
web:build: 18 | disabled={disabled}
web:build: 19 | {...rest}
web:build: ELIFECYCLE Command failed with exit code 1.
web:build: ERROR: command finished with error: command (/home/amm834/workspace/component-lib/apps/web) pnpm run build exited (1)
command (/home/amm834/workspace/component-lib/apps/web) pnpm run build exited (1)
Tasks: 0 successful, 1 total
Cached: 0 cached, 1 total
Time: 8.346s
ERROR run failed: command exited (1)
ELIFECYCLE Command failed with exit code 1.
➜ component-lib git:(main
StyledInput.tsx
import tw from "tailwind-styled-components";
import { IInputProps } from "./Input";
export const StyledInput = tw.input<IInputProps>`
mt-1 block w-full px-3 py-2 bg-white border border-slate-300 rounded-md text-sm shadow-sm placeholder-slate-400
focus:outline-none focus:border-zinc-500 focus:ring-1 focus:ring-zinc-500
invalid:border-pink-500 invalid:text-pink-600
focus:invalid:border-pink-500 focus:invalid:ring-pink-500
${({ disabled }) =>
disabled &&
"disabled:bg-slate-50 disabled:text-slate-500 disabled:border-slate-200 disabled:shadow-none"}
`;
Input.tsx
This is a ref wrapper for Styled Input.
import { ComponentPropsWithRef, forwardRef, PropsWithChildren } from "react";
import { useFieldId } from "./FieldContext";
import { StyledInput } from "./StyledInput";
export interface IInputProps
extends PropsWithChildren<ComponentPropsWithRef<"input">> {
disabled?: boolean;
}
export const Input = forwardRef<HTMLLabelElement, IInputProps>(
({ children, disabled, ...rest }, ref) => {
const id = useFieldId();
return (
<StyledInput
$as="input"
ref={ref}
id={id}
disabled={disabled}
{...rest}
/>
);
}
);
Input.displayName = "Field.Input";
It was a composite component like that.
import { nanoid } from "nanoid";
import { FC, PropsWithChildren, ReactNode } from "react";
import { FieldContext } from "./FieldContext";
import { Input } from "./Input";
import { Label } from "./Label";
import { TextArea } from "./TextArea";
interface IFieldComposition {
Label: typeof Label;
Input: typeof Input;
TextArea: typeof TextArea;
}
export const Field: FC<PropsWithChildren> & IFieldComposition = ({
children,
}) => {
const id = nanoid();
return (
<FieldContext.Provider value={{ id }}>{children}</FieldContext.Provider>
);
};
Field.Label = Label;
Field.Input = Input;
Field.TextArea = TextArea;
It is used something like that.
<Field>
<Field.Label>Email</Field.Label>
<Field.Input type="text" />
</Field>