I'm trying to import TextField and add inputMode prop from NumberField component. So I added inputMode in the interface
and also used ...rest
in the TextField in order to receive new props. But currently I'm getting this error:
Type '{ inputMode: "numeric"; onChange: (value: string) => void; value: string; }' is not assignable to type 'IntrinsicAttributes & ITextFieldProps & { children?: ReactNode; }'. Property 'inputMode' does not exist on type 'IntrinsicAttributes & ITextFieldProps & { children?: ReactNode; }'.
I'm not sure what I'm doing wrong. Just trying to add one more prop. Any advice would be appreciated. Source: https://codesandbox.io/s/numberfield-component-ts-wohlok?file=/src/NumberField.tsx:0-686
TextField.tsx
import React, { useState } from "react";
export interface ITextFieldProps {
type?: "text" | "search";
onChange?: (value: string) => void;
required?: boolean;
}
export const TextField: React.FunctionComponent<ITextFieldProps> = React.forwardRef<
HTMLInputElement,
ITextFieldProps
>((props, ref) => {
const { type = "text", onChange, required = true, ...rest } = props;
const [value, setValue] = useState("");
function handleChange(e: React.FormEvent<HTMLInputElement>) {
setValue(e.currentTarget.value);
onChange?.(e.currentTarget.value);
}
return (
<input
type={type}
value={value}
onChange={handleChange}
required={required}
{...rest}
/>
);
});
NumberField.tsx
import React, { useState } from "react";
import { ITextFieldProps, TextField } from "./TextField";
export interface INumberFieldProps extends ITextFieldProps {
inputMode?: "numeric";
}
export const NumberField: React.FunctionComponent<INumberFieldProps> = React.forwardRef<
HTMLInputElement,
INumberFieldProps
>((props, ref) => {
const { inputMode = "numeric", onChange } = props;
const [value, setValue] = useState("");
function handleChange(value: string) {
const updatedValue = value.replace(/\D/g, "");
setValue(updatedValue);
onChange?.(updatedValue);
}
return (
<TextField inputMode={inputMode} onChange={handleChange} value={value} />
);
});
CodePudding user response:
Your HTML should conform to standards. inputMode="numeric"
is not the right way to make a numeric input. The right way is type="number"
.
export interface ITextFieldProps {
type?: "text" | "search" | "number"; // <--- Add "number" here
onChange?: (value: string) => void;
required?: boolean;
}
Then in your NumberField.tsx
:
import React, { useState } from "react";
import { ITextFieldProps, TextField } from "./TextField";
export interface INumberFieldProps extends ITextFieldProps {
type?: "number"; // <--- Rename prop
onChange?: () => void;
}
export const NumberField: React.FunctionComponent<INumberFieldProps> = React.forwardRef<
HTMLInputElement,
INumberFieldProps
>((props, ref) => {
const { type = "number", onChange } = props; // <--- Rename prop
const [value, setValue] = useState("");
function handleChange(value: string) {
const updatedValue = value.replace(/\D/g, "");
setValue(updatedValue);
onChange?.(updatedValue);
}
return (
<TextField type={type} onChange={handleChange} value={value} /> // <--- Rename prop
);
});
This should work, but to further improve the code, you can omit the type
in INumberFieldProps
altogether, because its value can only ever be number
:
import React, { useState } from "react";
import { ITextFieldProps, TextField } from "./TextField";
export interface INumberFieldProps extends ITextFieldProps {
onChange?: () => void; // <--- Remove `type`
}
export const NumberField: React.FunctionComponent<INumberFieldProps> = React.forwardRef<
HTMLInputElement,
INumberFieldProps
>((props, ref) => {
const { onChange } = props; // <--- Remove `type`
const [value, setValue] = useState("");
function handleChange(value: string) {
const updatedValue = value.replace(/\D/g, "");
setValue(updatedValue);
onChange?.(updatedValue);
}
return (
<TextField type="number" onChange={handleChange} value={value} /> // <--- Hard-code `type="number"`
);
});
CodePudding user response:
inputMode
is not contained in the ITextFieldProps
interface, so you won't be able to access the property or assign a value to it.
Try adding [key: string]: any;
to the ITextFieldProps
interface if you don't know explicitly the type that you'll send as a prop like so:
export interface ITextFieldProps {
type?: "text" | "search";
onChange?: (value: string) => void;
required?: boolean;
[key: string]: any;
}
Then it should work.
Forked Sandbox: Sandbox