@RED2190

Ререндеринг при использовании setError?

Здравствуйте! Столкнулся со следующей проблемой:
1. нужно было сделать проверку валидности файла при использовании useForm, решил начать с одного параметра - веса. Написал функцию, а в документации нашел метод setError для последующей визуальной обработки ошибки.
2. Столкнулся с проблемой того, что errors в итоге пустой
3. При детальном разбере оказалось, что после загрузки файла и срабатывания ивента setError добавляет ошибку и по какой-то причине errors после этого очищается, я так понял, что это из за ререндеринга.
4. Нашел, что есть такие штуки, как useMemo и useCallback, но либо я их неправильно применил, либо дело в другом. Итог - errors остается пустым и пользователский выброс ошибки setError не сохраняется. Прошу добрых людей о помощи)
У меня уже глаз дергается....
function Upload( props ){
    console.log("Rendering")
    // объявление параметров
    const types = props.allowTypes ? props.allowTypes : null
    
    // ========
    const {register, handleSubmit, setError, formState: {errors} } = useForm({mode: 'all'})

    
    const id = useId()
    //===============
    const [fileName, setFileName] = useState("")
    const [fileSize, setFileSize] = useState("")
    const [step, setStep] = useState(1)
    // =================
    const uploadFile = async(values) =>{
        const formData = new FormData();
        formData.append("file", values.file[0]);
        const { data } = await axios.post("/upload", formData, {
            headers: {
              'Content-Type': 'multipart/form-data'
            }})
        console.log(data)
    }
    
    const onInputCallBack = useCallback((files) => {
        if( files[0].size > 150 ){
            setError('file', { type: 'custom', message: 'Недопустимый размер' });
        }
        setFileName(files[0].name);
        setFileSize(files[0].size);
        setStep( 2 )
    }, [fileName, fileSize, step, errors])
    
    return(
        <form className={styles.form} onSubmit={ handleSubmit(uploadFile) }>
            <div className={`${styles.step} ${styles.step1}`} active={(step === 1 ? "true": "false")}>
                <label htmlFor={id}>Выберите файл</label>
                <input type="file" id={id} {...register('file', { validate: (e) => onInputCallBack(e) } )}/>
                <p className="rule">* Размером до 150 кб.</p>
            </div>
            <div className={`${styles.step} ${styles.step2}`} active={(step === 2 ? "true": "false")}>
                <div className={styles.top}>
                    <div className={styles.name}>
                        <p>Название</p>
                        <span>{fileName}</span>
                    </div>

                    <div className={styles.size}>
                        <p>Размер</p>
                        <span>{fileSize} кб.</span>
                    </div>
                </div>
                
                { errors.file ? <><label className={styles.send} errors="true" htmlFor={id}>Загрузить</label><input type="file" onInput={ onInputCallBack } id={id} {...register('file')}/></> : <input className={styles.send} type="submit" value="Отправить" errors=""/> }                
                <div className={styles.alert}>{ errors.file ? errors.file.message : "" }</div>
            </div>
            <div className={`${styles.step} ${styles.step3}`} active={(step === 3 ? "true": "false")}>

            </div>
            
        </form>
    )
}

вот такой вот вывод получается:
668bd0d05ec0c588274410.png
  • Вопрос задан
  • 107 просмотров
Пригласить эксперта
Ответы на вопрос 1
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
Скорее всего, ваша проблема находится здесь:
if (files[0].size > 150) {
    setError('file', { type: 'custom', message: 'Недопустимый размер' });
}
...
setStep(2)

Вы идёте на следующий шаг даже при наличии ошибки валидации, вот у вас всё и перерендеривается.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
21 нояб. 2024, в 19:28
200000 руб./за проект
21 нояб. 2024, в 19:09
5000 руб./за проект
21 нояб. 2024, в 17:47
7000 руб./за проект