In my project, I am trying to add multiple emails as a chip. But I am facing a problem here, first time, when I paste multiple email values it gets inserted into the field, but second time when I copy some other values and paste them into the field, it replaces the previous values. to solve this added a line "setItem((i: string[]) => [...i, ...toBeAdded]);" inside "handlePaste". but this leads to another issue "Typescript: Argument of type '(i: string[]) => any[]' is not assignable to parameter of type 'string[]'."
type Props = {
LabelName?: string;
optional?: string;
tooltip?: string;
placeholder?: string;
className?: string;
upload?: boolean;
items?: any;
setItem: (items: string[]) => void;
};
const TagActions = (props: Props) => {
// const [items, setItem] = useState<string[]>([]);
const [value, setValue] = useState("");
const [error, setError] = useState("");
const divRef = useRef<HTMLDivElement>(null);
const [flag, setFlag] = useState(false);
const {
LabelName,
optional,
tooltip,
placeholder,
className,
upload,
items,
setItem,
} = props;
const handleDelete = (item: any) => {
const result = items.filter((i: any) => i !== item);
setItem(result);
};
const handleItemEdit = (item: any) => {
const result = items.filter((i: any) => i !== item);
setItem(result);
setValue(item);
};
const handleKeyDown = (evt: any) => {
if (["Enter", "Tab", ","].includes(evt.key)) {
evt.preventDefault();
const test = value.trim();
if (test && isValid(test)) {
items.push(test);
setValue("");
}
}
};
const isValid = (email: any) => {
let error = null;
if (isInList(email)) {
error = `${email} has already been added.`;
}
if (!validator.isEmail(email)) {
setFlag(true);
}
if (error) {
setError(error);
return false;
}
return true;
};
const isInList = (email: any) => {
return items.includes(email);
};
const handleChange = (evt: any) => {
setValue(evt.target.value);
};
const handlePaste = (evt: any) => {
evt.preventDefault();
const paste = evt.clipboardData.getData("text");
const emails = paste.match(/[\w\d\\.-] @[\w\d\\.-] \.[\w\d\\.-] /g);
if (emails) {
const toBeAdded = emails.filter((email: any) => !isInList(email));
console.log("items inside", items);
console.log("toBeAdded", toBeAdded);
setItem((i: string[]) => [...i, ...toBeAdded]);
console.log("items after", items);
}
};
return (
<>
<div className="formSection">
{LabelName && (
<div className={`control-label ${styles.label}`}>
<label>
<span className={styles.alignLeft}>
<span className={styles.labelText}>{LabelName}</span>
</span>
</label>
<span className={styles.alignRight}>
{upload && (
<label htmlFor="uploadCSV">
<span className={styles.upload}>Upload CSV</span>
</label>
)}
{optional && <span className={styles.light}>Optional</span>}
{tooltip && (
<span className={styles.tooltip_ic} title={tooltip}>
<FontAwesomeIcon icon={faCircleQuestion} size="xs" />
</span>
)}
</span>
</div>
)}
<input
type="file"
accept=".csv"
style={{ display: "none" }}
id="uploadCSV"
/>
<div className={styles.inputGroup}>
<TextField
className={` textfield-emailchip test ${className}`}
InputProps={{
startAdornment: items.map(
(
item:
| boolean
| Key
| ReactElement<any, string | JSXElementConstructor<any>>
| ReactFragment
| null
| undefined
| any
| string
) => (
<Chip
className={
!validator.isEmail(item)
? styles.chipTagError
: styles.chipTag
}
key={item}
tabIndex={-1}
label={item}
onDelete={() => handleDelete(item)}
onClick={() => handleItemEdit(item)}
deleteIcon={<FontAwesomeIcon icon={faXmark} size="xs" />}
/>
)
),
}}
ref={divRef}
value={value}
placeholder={placeholder}
onKeyDown={(e) => handleKeyDown(e)}
onChange={(e) => handleChange(e)}
onPaste={(e) => handlePaste(e)}
/>
</div>
{error && <p className="error">{error}</p>}
</div>
</>
);
};
export default TagActions;
Please give me a solution to fix this problem.
CodePudding user response:
setItem
is defined as having the type (items: string[]) => void
. This definition means it is a function that accepts an array of strings, for example setItem(['a', 'b', 'c'])
would be a valid invocation of a function with this type.
However, in the code setItem
is then called differently, like this:
setItem((i: string[]) => [...i, ...toBeAdded]);
The argument (i: string[]) => [...i, ...toBeAdded]
is not an array of strings; it is itself another function. TypeScript is saying this code is invalid because the argument given to setItem
is a function, not an array of strings.
You can either change the invocation to pass an array of strings, or change the definition to say it's supposed to accept a function, depending on which matches your true intent for the code.