как сделать setValue в useState был синхронным?
В функции onFromSubmit есть функция validateForm, которая при помощи хука useState устанавливает состояние валидации (true/false), но делает она это асинхронно, и после выполнения этой функции следующий код не получает нового значения, оно остается старым. Значение меняется только после выполнения onFormSubmit. Как это исправить / обойти?
import { addTodo } from "../../core/slices/todosSlice";
import { useAppDispatch} from "../../core/store/hooks";
import { v4 as uuidv4 } from 'uuid';
import useInput from "../../core/hooks/useInput";
import "./addTodoPanel.scss"
import { useValidateInput } from "../../core/hooks/useValidate";
type AddTodoPanelProps = {
readonly date: number
}
const AddTodoPanel: FC<AddTodoPanelProps> = ({date}) => {
const dispatch = useAppDispatch();
const [title, inputHandler, resetTitle] = useInput();
const [titleValid, validateTitle, titleStatus] = useValidateInput({minLength: 5, maxLength: 100});
const [descr, textareaHandler, resetDescr] = useInput();
const [descrValid, validateDescr, descrStatus] = useValidateInput({minLength: 10});
const resetForm = (): void => {
resetTitle(); resetDescr();
}
const validateForm = (): void => {
// setTitleValid false or true
validateTitle(title);
// setDescrValid false or true
validateDescr(descr);
}
const onFormSubmit: FormEventHandler<HTMLFormElement> = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
validateForm();
// тут должно поменяться значение validTitle и validDescr
// но оно меняется только после завершения функции onFormSybmit
// в titleValid и descrValid остается старое значение
if (!titleValid || !descrValid) {
return;
}
const todo = { title, descr, id: uuidv4(), time: 2020 }
dispatch(addTodo({ todo, date }))
resetForm();
}
return (
<form className="add-todo__form" onSubmit={onFormSubmit}>
<FormItemLayout label="title" isValid={titleValid} errorMessage={titleStatus}>
<input className="add-todo__input" onChange={inputHandler} value={title}/>
</FormItemLayout>
<FormItemLayout label="description" isValid={descrValid} errorMessage={descrStatus}>
<textarea className="add-todo__textarea" onChange={textareaHandler} value={descr}></textarea>
</FormItemLayout>
<button className="add-todo__button" type="submit">Add todo</button>
</form>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
хук useValidateInput:
import { useState } from "react"
type UseValidateProps = {
readonly minLength: number,
readonly maxLength?: number | null
}
export const enum UseValidateStatus {
confirm = 'confirm',
strLengthOutOfRangeException = 'str length out of range exception',
strLengthLessThenMinLength = 'str length less then min length'
}
type UseValidateInputReturn = [
boolean,
(str: string) => void,
UseValidateStatus
]
export const useValidateInput = ({
minLength = 20,
maxLength = null
}: UseValidateProps): UseValidateInputReturn => {
const [isValid, setIsValid ] = useState<boolean>(true);
const [status, setStatus] = useState<UseValidateStatus>(UseValidateStatus.confirm);
const validateValue = (str: string): void => {
if (maxLength) {
if (str.length > maxLength) {
setIsValid(isValid => false);
setStatus(UseValidateStatus.strLengthOutOfRangeException);
} else {
setIsValid(isValid => true);
setStatus(UseValidateStatus.confirm);
}
}
if (str.length < minLength) {
setIsValid(isValid => false);
setStatus(UseValidateStatus.strLengthLessThenMinLength);
} else {
setIsValid(isValid => true);
setStatus(UseValidateStatus.confirm);
}
}
return [isValid, validateValue, status]
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>