In my simple crud application, when I try to add a new author with an invalid name format and try to submit form display an error and after that when I have press backspace twice to erase last letter in textbox.
Here is my AuthorForm.tsx
import React, {useEffect, useState} from 'react';
import {Row, Col, Form, Button} from 'react-bootstrap';
import {IAuthor} from "../../assets/types/LibraryTypes";
import {XCircle} from "react-feather";
import {useForm} from "react-hook-form";
interface IFormInputs {
authorName: string
}
type CreateFormProps = {
onClose: () => void,
onAuthorAdded: (author:IAuthor)=>void,
onAuthorToUpdate: IAuthor | null,
updateAuthorIndex : number | null,
onAuthorUpdated : (updatedAuthor:IAuthor, index:number)=>void,
}
const AuthorForm:React.FC<CreateFormProps> = (props) =>{
const [authorName, setAuthorName] = useState<string|null>(null);
const { register, errors, handleSubmit } = useForm<IFormInputs>({mode:'onTouched'});
useEffect(()=>{
if(!props.onAuthorToUpdate){
setAuthorName(null);
return;
}
setAuthorName(props.onAuthorToUpdate.name);
},[props.onAuthorToUpdate]);
const handleOnNameChange = (event:React.ChangeEvent<HTMLInputElement>)=>{
event.preventDefault();
setAuthorName(event.target.value);
}
const handleOnCreate = () =>{
if(!authorName){
return;
}
if(props.onAuthorToUpdate && props.updateAuthorIndex !== null){
props.onAuthorUpdated({...props.onAuthorToUpdate,name:authorName},props.updateAuthorIndex);
setAuthorName(null);
return;
}
const newAuthor: IAuthor = {name:authorName};
props.onAuthorAdded(newAuthor);
setAuthorName(null);
};
return(
<Col className='p-0' sm={10}>
<Row className=' pb-1 mb-3 mx-1'>
<Col xs={10}>
<span className='add-book-title pt-2'>
{!props.onAuthorToUpdate && 'Create Author'}
{props.onAuthorToUpdate && 'Update Author'}
</span>
</Col>
<Col className='closeBtn text-right p-0' xs={2}>
<XCircle color='#363636' className='mt-2 mr-3' onClick={props.onClose}/>
</Col>
</Row>
<Form className='mx-4' onSubmit={handleSubmit(handleOnCreate)}>
<Form.Group>
<Form.Row>
<Form.Label column="sm" xs={6} className='label'>
Name of the Author
</Form.Label>
<Col xs={6} className='warning text-right mt-2 pr-2'>
{errors.authorName?.type === "required" && (
<p>This field is required</p>
)}
{errors.authorName?.type === "maxLength" && (
<p>Author Name name cannot exceed 50 characters</p>
)}
{errors.authorName?.type === "pattern" && (
<p>Invalid Author Name</p>
)}
</Col>
<Col sm={12}>
<Form.Control size={"sm"}
name="authorName"
ref={register({
required: true,
maxLength: 50,
pattern: /^[a-zA-Zs]+$/
})}
onChange={
(event:React.ChangeEvent<HTMLInputElement>)=>
handleOnNameChange(event)
}
value={authorName?authorName:''}
/>
</Col>
</Form.Row>
</Form.Group>
<Col className='text-right mb-3 p-0' xs={12}>
<Button type={"submit"} variant={"primary"} size={"sm"} className={"px-3 pt-1"}>
{!props.onAuthorToUpdate && 'Create'}
{props.onAuthorToUpdate && 'Update'}
</Button>
</Col>
</Form>
</Col>
)
};
export default AuthorForm;
And this is AuthorList.tsx
import React, {useEffect, useState} from 'react';
import {Container} from 'react-bootstrap';
import AuthorAddedList from "./AuthorAddedList";
import AuthorForm from "./AuthorForm";
import AuthorWelcome from "./AuthorWelcome";
import CreateAuthor from "./CreateAuthor";
import {IAuthor} from "../../assets/types/LibraryTypes";
const AuthorList:React.FC = () =>{
const initAuthors: IAuthor[] = [];
const [authors, setAuthors] = useState<IAuthor[]>(initAuthors);
const [isFormVisible, setIsFormVisible] = useState<boolean>(false);
const [authorToUpdate, setAuthorToUpdate] = useState<IAuthor | null>(null);
const [updateAuthorIndex, setUpdateAuthorIndex] = useState<number| null>(null)
useEffect(()=>{
if(!authorToUpdate){
return;
}
setIsFormVisible(true);
},[authorToUpdate]);
const handleOnCreateClick = () => {
setIsFormVisible(true);
setAuthorToUpdate(null);
};
const handleOnFormClosed = () => {
setIsFormVisible(false);
}
const handleAuthorAdded = (newAuthor: IAuthor) => {
const allAuthors: IAuthor[] = authors.slice();
allAuthors.push(newAuthor)
setAuthors(allAuthors);
};
const handleAuthorDeleted = (index: number) => {
const allAuthors: IAuthor[] = authors.slice();
allAuthors.splice(index, 1);
setAuthors(allAuthors);
}
const handleOnUpdateRequest = (index: number) => {
setAuthorToUpdate(authors[index]);
setUpdateAuthorIndex(index);
setIsFormVisible(true);
}
const handleOnAuthorUpdated = (updatedAuthor: IAuthor, index:number) =>{
const allAuthors : IAuthor [] = authors.slice();
allAuthors.splice(index,1, updatedAuthor);
setAuthors(allAuthors)
}
return (
<Container fluid={true} className={"authors"}>
<AuthorWelcome/>
<AuthorAddedList authors={authors} onDeleted={handleAuthorDeleted} onUpdateRequested={handleOnUpdateRequest} />
<CreateAuthor onClickCreate={handleOnCreateClick}/>
{isFormVisible &&
<AuthorForm onClose={handleOnFormClosed} onAuthorAdded={handleAuthorAdded} onAuthorToUpdate={authorToUpdate} onAuthorUpdated={handleOnAuthorUpdated} updateAuthorIndex={updateAuthorIndex}/>}
</Container>
)
}
export default AuthorList;
Here is the sandbox link to my full code Click Here
to demonstrate the error,
- go to the sandbox link
- click add author button in webapp
- enter an invalid name like 'john97'
- then submit the form
- then try to clear the name using backspace.
- now you can see to erase last letter 'j' you have to press backspace twice
please help me to solve this issue
thank you
question from:https://stackoverflow.com/questions/66054594/react-hooks-form-onchange-misbehave-after-error-validation-occured