I have a Curriculum Vitae form that does not send the data unless two sections are completely filled. For testing purposes none of the fields are required. Furthermore I am getting the error:
POST http://localhost:8000/api/jobApplications net::ERR_CONNECTION_RESET
The issue is because there are 2 sections in the CV, Education and Work Experience, that have aggregate fields when clicking on a button that adds a new Education/Work field row. If all these fields within these rows aren't filled, it will not send.
The input fields' name and value in the Education and Work sections have a functionality where when you click on add new row of fields, it will replace/change the letter in both the input name and value.
Here are the useState hooks:
const [inputValue, setInputValue] = useState<JobApplicationInterface>(JobApplicationForm);
const [divEducationList, setDivEducationList] = useState<number[]>([]);
const [divWorkList, setDivWorkList] = useState<number[]>([]);
const [divEducation, setDivEducation] = useState<number>(0);
const [divWork, setDivWork] = useState<number>(0);
const [arrayEducation, setArrayEducation] = useState<ArrayLettersInterface[]>(arrayLetters);
const [arrayWork, setArrayWork] = useState<ArrayLettersInterface[]>(arrayLetters);
Here's the Education section (the Work Experience section is basically the same, except has the option to add more fields - Education is limited at 3 rows of fields and Work is limited to 5).
EDUCATION SECTION
<div className='input-group-container education-container'>
<div className='input-group education-group'>
<div className='input-container input-wrapper'>
<Select
title='Education Degree'
name='education_a_degree'
value={inputValue.education_a_degree}
optionList={degreeSelectOptionArray}
handleSelect={handleSelect}
/>
</div>
<div className='input-container input-wrapper'>
<Input
title='University'
type='text'
value={inputValue.education_a_school}
name='education_a_school'
handleInput={handleInput}
/>
</div>
...MORE INPUTS (type=text)...
<div className='btn-group-container education-btns'>
<Button
btnTitle={<Add />}
handleClick={handleClickAddEducation}
/>
</div>
</div>
{divEducationList.map((_, index: number) => (
<div className='input-group education-group' key={index}>
<div className='input-container input-wrapper'>
<Select
title='Education Degree'
value={inputValue[`education_${arrayLetters[index].letter}_degree`]}
name={`education_${arrayLetters[index].letter}_degree`}
optionList={degreeSelectOptionArray}
handleSelect={handleSelect}
/>
</div>
<div className='input-container input-wrapper'>
<Input
title='University'
type='text'
value={inputValue[`education_${arrayLetters[index].letter}_school`]}
name={`education_${arrayLetters[index].letter}_school`}
handleInput={handleInput}
/>
</div>
...MORE INPUTS (type=text)...
<div className='btn-group-container education-btns'>
{!divEducationList?.[1] ? (
<Button
btnTitle={<Add />}
handleClick={handleClickAddEducation}
/>
) : null}
<Button
btnTitle={<Remove />}
handleClick={(event: React.ChangeEvent<HTMLInputElement>) =>
handleClickRemove(event, index, 'education')
}
/>
</div>
</div>
))}
</div>
I have 2 functions for adding a new row of fields, one for Education and the other for Work, and they are the same. This function also adds a new letter ('a', 'b', 'c',...) to all of the row's input names and values each time a new row is added.
HANDLECLICKS
const handleClickAddEducation = () => {
if (divEducationList.length < 2) {
for (let i = 0; i < divEducationList.length; i++) {
if (arrayLetters[i].index === i) {
setArrayEducation((prev: any) => ({
...prev,
[i]: arrayLetters[i].letter,
}));
}
}
setDivEducation((divEducation: number) => divEducation + 1);
return setDivEducationList((divEducationList: any) => [
...divEducationList,
divEducation,
]);
} else {
throw new Error('too many selected');
}
};
const handleClickAddWork = () => {
if (divWorkList.length < 2) {
for (let i = 0; i < divWorkList.length; i++) {
if (arrayLetters[i].index === i) {
setArrayWork((prev: any) => ({
...prev,
[i]: arrayLetters[i].letter,
}));
}
}
setDivWork((divWork: number) => divWork + 1);
return setDivWorkList((divWorkList: any) => [
...divWorkList,
divWork,
]);
} else {
throw new Error('too many selected');
}
};
This is the handle input:
HANDLEINPUTS
const handleInput: React.ChangeEventHandler<HTMLInputElement> | undefined = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const value = event.target.value;
const name = event.target.name;
setInputValue((prev) => ({ ...prev, [name]: value }));
};
For the POST request I use Axios and FormData, and submitting to the server is not an issue, unless, as mentioned above, Education/Work sections are not completely filled.
HANDLESUBMIT
const handleSubmit: React.FormEventHandler<HTMLFormElement> = (
event: React.FormEvent<HTMLFormElement>
) => {
event.preventDefault();
setIsLoading(true);
let keys = Object.keys(inputValue);
let values = Object.values(inputValue);
for (let i = 0; i < keys.length; i++) {
formData.append(keys[i], values[i] as unknown as Blob);
}
axios
.post(postApiUrl, formData, postHeaders)
.then((response) => {
console.log(response.data);
})
.catch((err) => {
const error =
err.code === 'ECONNABORTED'
? 'A timeout has occurred'
: err.response.status === 404
? 'Resource not found'
: 'An unexpected error has occurred';
setError(error);
setIsLoading(false);
})
.finally(() => setIsLoading(false));
};
If you require more information, please let me know, thanks!