Почтовый вызов Axios работает, но другой код не запускается, состояние не обновляется

Во внешнем интерфейсе есть функция, которая обрабатывает загрузку файла и отправляет его на серверную часть для обработки. Затем бэкэнд возвращает json, который следует использовать для обновления моего состояния React. Я настроил тестовый вызов с помощью axios.get(), который работает нормально, когда серверная часть передает строку, отображаемую на веб-странице. console.info() также отлично работает в этой тестовой функции. Однако когда дело доходит до моей функции uploadDoc, console.info() не запускается и состояние не обновляется. Вот мой код:

Приложение.js

const documentUploadHandler = ({files}) => {
    const [file] = files;
    uploadDoc(file);
  };

  const uploadDoc = async (document) => {
    console.info(doc_type)
    document.preventDefault();
    let formData = new FormData();
    formData.append('document', document);

    try {
      const response = await axios.post('https://127.0.0.1:8000/api/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      });

      setDocType([response.data.classification]);
      console.info("hello")
      console.info(response.data);

    } catch (error) {
      console.info('Error uploading file:', error);
    }
  };

Сервер.py

@app.route('/api/upload', methods=['POST', 'GET'])
@cross_origin(supports_credentials=True)
def upload_file():
    global class_result
    if request.method == 'POST':
        try:
            file = request.files['document']
            print(f"Uploading document {file.filename}")
            filename = secure_filename(file.filename)
            file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            file.save(file_path)
            class_result = classify_document("model5", file_path)
            return jsonify({"status": "get_success", "classification": class_result})

        except Exception as e:
            print(f"Couldn't upload document: {e}")
            return jsonify({"status": "failed", "error": str(e)})
    return jsonify({"status": "post_success", "classification": class_result})

Я попытался выполнить вызов API в Postman, который, как ни странно, дает мне статус успеха только тогда, когда я делаю запрос GET, а не запрос POST. Я не уверен, имеет ли это отношение к моей проблеме. Я проверил с помощью инструментов разработки на вкладке «Сеть», и он дал мне код состояния 200 и сказал, что мой метод запроса — POST, поэтому, похоже, он использует правильный тип запроса в Интернете.

Я также попробовал обновить состояние в отдельной функции с помощью axios.get(). Это работает в том смысле, что новое состояние отображается, но только после того, как я обновлю страницу. Однако мне нужно, чтобы состояние обновлялось, как только серверная часть завершит обработку файла, поэтому я пытаюсь обновить состояние после моего вызова axios.post().

🤔 А знаете ли вы, что...
С Python можно создавать настольные приложения с использованием библиотеки Tkinter.


54
1

Ответ:

Решено

Короче говоря, axios.post создает обещание, а не реальную ценность. Обещание — это то, что необходимо правильно обработать, когда обещание выполнено (поскольку это асинхронный вызов). Обычно с .then((r)=>{setState(r)});

Итак, для вашего случая этого должно быть достаточно:

axios.post('https://127.0.0.1:8000/api/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
      }).then((response)=>{
      setDocType([response.data.classification]);
      console.info("hello")
      console.info(response.data);
      })
      .catch(err => {
        // Handle errors
        console.error(err);
    });

Пример реализации компонента, обратите внимание на анализ json, это применимо только в том случае, если они на самом деле являются результатами json:

export default function UploadFiles() {
    const [files, setFiles] = useState<File[]>([]);
    const filesRef = useRef(null);
    filesRef.current = files;
    const [backendAnswer, setBackendAnswer] = useState<any>();

    const handleFileSelect = useCallback((event: ChangeEvent<HTMLInputElement>) => {
        if (event.target.files.length === 0) setFiles([]);
        else setFiles([...event.target.files]);
    }, []);

    const uploadFiles = useCallback(() => {
        if (filesRef.current.length != 1) return;
        let formData = new FormData();
        formData.append('document', filesRef.current[0]);

        axios.post('https://127.0.0.1:8000/api/upload', formData, {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
        }).then((response) => { 
            if (!response.ok) throw new Error("Error in request at " + url);
            else return response.json();
        }).then((jsonParsedResponse)=>{
            console.info(jsonParsedResponse)
            setBackendAnswer(jsonParsedResponse);
        }).catch((error) => { console.error(error) });
    }, []);

    return <>
        <div className = "flex flex-col">
            <label
                htmlFor = "fileUpload"
            >
                Select files
                <input
                    id = "fileUpload"
                    name = "fileUpload"
                    type = "file"
                    className = "hidden"
                    onChange = {handleFileSelect}
                />
            </label>
        </div>
        <button onClick = {uploadFiles} >Upload</button>
    </>
}