React onSubmit e.preventDefault() иногда не работает + Axios

Прямо сейчас я столкнулся с этой странной проблемой в React, где функция onSubmit с e.preventDefault() иногда избегает обновления страницы, а иногда нет.

Я создал два хука для отслеживания загруженных файлов и их индикаторов выполнения.

const [ uploadedFiles, setUploadedFiles ] = useState([]);
const [ uploadPercentages, setUploadPercentages ] = useState([]);

Функция onSubmit использует Axios для выполнения запроса к серверной части.

const onSubmit = async e => {
        e.preventDefault();

        if(!!file) {
            // Show file box on screen
            let index = addUpload(file);

            const formData = new FormData();
            formData.append("file", file);

            try {
                await axios.post("/upload_video", formData, {
                    onUploadProgress: progressEvent => {
                        const { loaded, total } = progressEvent;
                        let progress = uploadPercentages.concat(0)
                        progress[index] = Math.round((loaded * 100) / total)

                        setUploadPercentages(progress);
                    }
                })
            } catch(err) {
                // Handlers
            }
        }
        return false // trying something different to avoid refresh
}

На всякий случай, функция addUpload практически не имеет отношения к источнику проблемы. Я забрал его, чтобы проверить, и все ведет себя так же.

Если кто-нибудь может помочь, я был бы признателен.

Редактировать:

Вот форма.

<form className="choose-file" onSubmit={onSubmit}> 
            
     <div className="file-container">
         { file ?
             <p> { file.name } </p>
             :
             <label className="file-label" htmlFor="customFile">
                 <input type="file" className="file-input" id="customFile" onChange={ onChange }/>
                 <p><i className="fas fa-cloud-upload-alt"></i></p>
                 <p>Click here to select file</p>
             </label>   
          }
     </div>

     <div className="file-options">
          <input type="submit" value="Upload" className="file-input" id="customFile"/>
          <button type="button" onClick={ removeFile }>Delete</button>
     </div>

</form>

file — это третий хук, просто чтобы показать пользователю имя файла, который он только что выбрал.

Редактировать 2:

Проблемы появляются только тогда, когда размеры файлов превышают 100 МБ. Кроме того, как только проблема появляется, она начинает случаться с каждым файлом независимо от его размера.

Например, если я загружаю файл размером 7 МБ, страница не обновляется, если я затем пытаюсь загрузить файл размером 100 МБ, он начинает обновляться для каждого следующего файла, и все журналы консоли после сообщения axios больше никогда не отображаются.

Редактировать 3:

Поскольку я запускаю локальный сервер на Flask, я попытался отключить его от приложения React, чтобы посмотреть, что произойдет. Для небольших файлов запрос к бэкенду запрашивается только один раз, и срабатывает сигнализация внутри catch(err). Для больших файлов запрос запрашивается около четырех раз, и он никогда не достигает части захвата.

Отправить помощь


person Manuel Mendoza    schedule 04.10.2020    source источник
comment
покажи нам свою форму тоже.   -  person cybercoder    schedule 04.10.2020
comment
@cybercoder конечно!   -  person Manuel Mendoza    schedule 04.10.2020
comment
Вы можете попробовать удалить async в функции onSubmit и соответствующим образом изменить код axios.   -  person deepakgupta191199    schedule 04.10.2020
comment
@deepakgupta191199 да, я попробовал это, и это не сработало. Журналы консоли после метода axios также не отображаются   -  person Manuel Mendoza    schedule 04.10.2020
comment
что произойдет, если вы вызовете это так: form onsubmit={e=>{e.preventDefault(); onSubmit()}} и удалите событие из своей функции?   -  person cybercoder    schedule 04.10.2020
comment
@cybercoder все еще обновляется. Я также помещаю некоторые журналы консоли после axios, и они не отображаются, когда файл слишком большой (100 МБ+). Я добавлю новую информацию, которую я собрал, к основному вопросу.   -  person Manuel Mendoza    schedule 04.10.2020
comment
Вы уверены, что в родительских компонентах есть пометки, которые влияют? это странно!   -  person cybercoder    schedule 04.10.2020
comment
@cybercoder да, сейчас это единственный компонент в проекте. Была информация о файле рендеринга второго компонента, но я ее убрал, и ничего не изменилось.   -  person Manuel Mendoza    schedule 04.10.2020
comment
Возможно, вам нужно установить для maxContentLength и maxBodyLength значение Infinity. См. этот ответ: stackoverflow.com/a/63611054/12200445   -  person deepakgupta191199    schedule 04.10.2020
comment
@deepakgupta191199 нет, это не работает. Что-то странное в том, что axios не отображает ошибки, когда это происходит.   -  person Manuel Mendoza    schedule 04.10.2020


Ответы (3)


Думаю проблема не в addUpload, а в async. Вы можете попробовать этот способ

const onSubmit = (e) => {
 e.preventDefault();
 
 // After collecting formData ... 
 // in the *try* block do this
 
 const post = axios.post("/upload_video", formData, {
                    onUploadProgress: progressEvent => {
                        const { loaded, total } = progressEvent;
                        let progress = uploadPercentages.concat(0)
                        progress[index] = Math.round((loaded * 100) / total)

                        setUploadPercentages(progress);
                    }
  
  post.then(() => {alert('Done posting')}) // inside this you can do whatever you want to do after axios.post 
}

**РЕДАКТИРОВАТЬ : **

Поскольку вы упомянули в комментарии, что решение не работает, вот альтернатива.

Объявить новую функцию

const async post = () => {
 // Get the formData here

 await axios.post("/upload_video", formData, {
                    onUploadProgress: progressEvent => {
                        const { loaded, total } = progressEvent;
                        let progress = uploadPercentages.concat(0)
                        progress[index] = Math.round((loaded * 100) / total)

                        setUploadPercentages(progress);
                    }
}

// Now in the onSubmit function

const onSubmit =  (e) => {
 
 e.preventDefalut();
 post()
}

Это окончательное решение, которое у меня есть. Надеюсь, это сработает...

person Hard Code Programmer    schedule 04.10.2020
comment
Спасибо, но это не работает, хотя важно упомянуть, что предупреждение внутри .then() так и не появилось. - person Manuel Mendoza; 04.10.2020
comment
Попробуйте новую отредактированную версию. - person Hard Code Programmer; 04.10.2020
comment
Извините, но это не сработало. Я попробовал предупреждение в .then() еще раз, чтобы увидеть, всплывает ли оно, но это тоже не так. - person Manuel Mendoza; 04.10.2020

У меня возникли проблемы с использованием стрелочных функций в качестве HANDLERS, попробуйте превратить их в обычные функции.

async function HandelOnSubmit (e) {
        e.preventDefault();

        if(!!file) {
            // Show file box on screen
            let index = addUpload(file);

            const formData = new FormData();
            formData.append("file", file);

            try {
                await axios.post("/upload_video", formData, {
                    onUploadProgress: progressEvent => {
                        const { loaded, total } = progressEvent;
                        let progress = uploadPercentages.concat(0)
                        progress[index] = Math.round((loaded * 100) / total)

                        setUploadPercentages(progress);
                    }
                })
            } catch(err) {
                // Handlers
            }
        }
        return false // trying something different to avoid refresh }
person Ahmed Magdy    schedule 04.10.2020

В конце концов проблема оказалась такой простой, как сохранение файлов в общей папке React.

Я предполагаю, что это привело к обновлению всего проекта каждый раз, когда в этой папке обнаруживается изменение. Для небольших объектов это занимает почти нулевое время, но для больших файлов требуется некоторое время, что также приводит к обновлению компонентов.

person Manuel Mendoza    schedule 04.10.2020