In my project, using useState to initialize values, I am a beginner in React TypeScript. So I don't know how to replace them with interface or type. I referred some documentation to solve this but didn't get the expected result.
import React, { useRef, useState } from "react";
import ReactDOM from "react-dom";
import Chip from "@material-ui/core/Chip";
import TextField from "@material-ui/core/TextField";
interface details{
value: string;
emails: Array<string>;
error?: string | null;
item?:string;
}
export const TagActions = () => {
const [items, setItem] = useState<string[]>([]);
const [value, setValue] = useState('')
const [error, setError]= useState('')
const divRef = useRef<HTMLDivElement>(null)
const handleDelete = (item:any) => {
console.log("handleDelete", item)
const result = items.filter(i => i !== item)
setItem(result)
};
const handleItemEdit = (item:any) =>{
console.log("handleItemEdit", item)
const result = items.filter(i => i !== item)
setItem(result)
setValue(item)
console.log("value", value)
};
const handleKeyDown = (evt:any) => {
if (["Enter", "Tab", ","].includes(evt.key)) {
evt.preventDefault();
var 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 (!isEmail(email)) {
error = `${email} is not a valid email address.`;
}
if (error) {
setError(error);
return false;
}
return true;
}
const isInList = (email:any)=> {
return items.includes(email);
}
const isEmail = (email:any)=> {
return /[\w\d\.-] @[\w\d\.-] \.[\w\d\.-] /.test(email);
}
const handleChange = (evt:any) => {
setValue(evt.target.value)
// setError("")
};
const handlePaste = (evt:any) => {
evt.preventDefault();
var paste = evt.clipboardData.getData("text");
var emails = paste.match(/[\w\d\.-] @[\w\d\.-] \.[\w\d\.-] /g);
if (emails) {
var toBeAdded = emails.filter((email:any) => !isInList(email));
setItem(toBeAdded)
}
};
return (
<>
<div>
<TextField id="outlined-basic" variant="outlined"
InputProps={{
startAdornment: items.map(item => (
<Chip
key={item}
tabIndex={-1}
label={item}
onDelete={() => handleDelete(item)}
onClick={() => handleItemEdit(item)}
/>
)),
}}
ref={divRef}
value={value}
placeholder="Type or paste email addresses and press `Enter`..."
onKeyDown={(e) => handleKeyDown(e)}
onChange={(e) => handleChange(e)}
onPaste={(e) => handlePaste(e)}
/>
</div>
{error && <p className="error">{error}</p>}
</>
);
}
Currently, setItem, setValue, and setError are used to update corresponding values. So how about using "details" instead?, Please give me some suggestions to overcome this issue.
CodePudding user response:
You can work with the entire object like that:
interface IDetails {
value: string;
emails: Array<string>;
error?: string | null;
item?:string;
}
const [details, setDetails] = useState<IDetails>({/*Your initial state here*/});