質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

2回答

5808閲覧

【React×FastAPI】axiosでAPIを叩き値を返したい

TAMANEKO

総合スコア9

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

1クリップ

投稿2021/06/11 17:10

編集2021/06/12 04:30

【React×FastAPI】axiosでAPIを叩き値を返したいが値は返らずエラーも出ない

概要

React で簡単な SPA を作成し Firebase にデプロイしました.その中で文字列を送信する Form を作成してあります.

バックエンドは FastAPI で作成して Deta という PaaS/BaaS にデプロイしてあります.

フロントエンドとバックエンドが繋げられているかテストするために,Form から文字列が送信されたらバックエンド側で別の文字列を付け足して返す,という処理をしようとしています.

できないこと

Form が送信されると axios がバックエンドの API を叩くようにしようとしていますが,意図通りに動作しません.

Form が送信されバックエンドの API が叩かれている形跡はあるが値が返ってこない上にエラーなども出ていない

やったこと

  • フロントはローカルで立ち上げたもので実行してもデプロイしたものから実行しても挙動は同じ
  • Form を作成し TextField ( materialUI ) に入力された文字列を送信する
  • バックエンドは FastAPI ( Python ) で作成し Deta という PasS / BaaS にデプロイ済み
  • エラーメッセージなどは一切でない
  • サーバのログには 200 番で成功した旨が表示されている
  • Postman や curl で叩くと成功している

環境

  • ローカル: MacOSX Big Sur 11.4
  • フロントエンド: React
  • バックエンド: FastAPI
  • サーバ: Deta Micros

背景

React と FastAPI を使ってフロントとバックエンドをつないだアプリ開発の勉強を独学で行っています.ベストプラクティスなどはきちんと把握しておらず基本的には使っている技術のドキュメントに沿って進めています.

デバッグ

  • React で Form を作成 ( materialUI の TextField, Button を使用 )
  • Form が送信されるとサービスクラスのメソッドが呼ばれる
  • このメソッドに axios.get() がある
  • axios.get() の前後にある console.log は表示されるが axios.get()に繋げた .then().catch.finally() は動いていない
  • デプロイされているサーバのログに実行されたログがあり 200 で正常に動いている
  • ログには get で送られてきたデータも入っている上バックエンドの処理も実行されており問題ないように見える
  • なので axios.get() 自体は動いているが then() には入らないという状態?
  • ブラウザのデベロッパツールでネットワークを確認するもエラーなどは何もない

ソースコード

フロント

  • React ( src/screens/Screen.jsx )
import React, { useState, useCallback } from "react"; import EdgeBar from "../components/EdgeBar"; import Box from "@material-ui/core/Box/Box"; import TextField from "@material-ui/core/TextField"; import { makeStyles, Grid, Typography, Button } from "@material-ui/core/"; import ApiTest from "../services/test/apiTest"; // API を叩くためのクラス . . スタイル省略 . const screen = () => { const classes = useStyles(); const [text, setText] = useState(""); // フォームの入力を入れるstate const changeInput = useCallback((event) => { setText(event.target.value); // フォームの入力を取得 }, []); // うまく行かないのはここ const handleSubmit = useCallback(async () => { const response = await ApiTest.getText(text); // API を叩くためのクラス ( apiTest.js へ ) console.log("response: ", response); // 表示される alert("response: " + response); // これが表示されるが }, [text]); return ( <EdgeBar title=""> <Typography className={classes.title}> Credibility Assessment System </Typography> <Typography className={classes.title}>Now in Preparation...</Typography> <Box className={classes.contentArea} p={1} m={1}> <Grid className={classes.paragraph}> <form className={classes.from} onSubmit={handleSubmit} noValidate autoComplete="off" > <TextField className={classes.textField} label="INPUT TEXT" variant="outlined" value={text} onChange={changeInput} /> <Button className={classes.button} type="submit" variant="contained" disableElevation > submit </Button> </form> </Grid> </Box> </EdgeBar> ); }; export default Screen;
  • src/services/test/apiTest.js
// テスト用のクラス const axios = require("axios").default; const url = "https://url.dev"; // あっている export default class CredibilityAssessment { static getText(text) { console.log("START"); // 表示される axios .get(`${url}test/${text}`) // PATH もあっている ( サーバのログを見ると実行されている ) .then((res) => { console.log("success: ", res.data); // 表示されないので何故かここには入ってこない return res.data; // 返されない }) .catch((err) => { console.log("failed: ", err); // 表示されない return err; // 返されない }) .finally((res) => { console.log("failed: ", res.data); // 表示されない return res; // 返されない }); console.log("END"); // 表示される return "axios skipped"; // 返される } }

バックエンド

  • app/main.py ( Deta にデプロイされている fastapi )
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware from services.test import TestClass # Generate FastAPI instance app = FastAPI() # CORSを回避するための設定 app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # Routing @app.get("/") async def root(): return {"message": "It Works!"} # 動作確認用 @app.get("/test/{text}") async def test(text): res = TestClass.test(text) // test.py へ return {"message": res}
  • app/services/test.py
class TestClass: # 動作確認用 def test(text): return "API works! " + text

備考

  • react や nodejs, axios, fastapi, Deta はすべて初めて使っています.
  • 変数名・関数名などが適当ですみません,サクッと試そうとしたため適当になっています
  • 説明のためにコメントをたくさん残しました
  • 問題が React なのか JS の書き方なのか FastAPI なのかサーバーの設定なのか,それとも他に何かあるのか,切り分けができていない状態です

公式ドキュメントや Google を活用してあらゆる方法をためしたのですが一日経っても解決しなかったため質問させていただきます.

書き方も then catch ではなく async await にしたり jsx のフォームを変えたりしてみましたがうまく動作しませんでした.

サーバーのログに実行の形跡があるパターンと,そもそも API が叩かれていない時と2パターンあります.

助けていただけると幸いです!
よろしくお願いいたします!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

自己解決しました!
jsx のフォームの handleSubmit を以下のように変更することで正常に動作するようになりました.

const handleSubmit = useCallback( async (e) => { e.preventDefault(); // 追加した行 const response = await CredibilityAssessmentService.assessCredibility( formText ); alert("response: " + response.message); }, [formText] );

フォームのデフォルトの挙動としてページがリロードされるためサーバ側の処理が実行されてはいるが、すぐに画面が更新され画面に alert が表示されないということが起こっていたようです.該当の行を追加することでフォームのデフォルトのページリロードを走らないようにできるようです。

ご協力してくださりありがとうございました.

投稿2021/06/15 04:23

編集2021/06/15 09:23
TAMANEKO

総合スコア9

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

少し手元で試せていないのですが
取り急ぎ見た限りですとaxiosの通信が非同期のため、リターン値は実行後に返せておらず、最後に記載されたリターンによって、想定した動きになっていないのかと思われます。
下記でいかがでしょうか?

javascript

1axios 2 .get(`${url}test/${text}`) // PATH もあっている ( サーバのログを見ると実行されている ) 3 .then((res) => { 4 console.log("success: ", res.data); // 表示されないので何故かここには入ってこない 5 return res.data; // 返されない 6 }) 7 .catch((err) => { 8 console.log("failed: ", err); // 表示されない 9 return err; // 返されない 10 }) 11 .finally((res) => { 12 console.log("failed: ", res.data); // 表示されない 13 return res; // 返されない 14 }); 15//最後のリターンを削除

投稿2021/06/12 13:24

m2l

総合スコア318

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TAMANEKO

2021/06/13 06:18

m2l さん 回答していただきありとうございます! 上げていただいたソースコードの通りに非同期処理のあとの return を削除したのですが結果は変わりませんでした... 画面に表示される値が undefined になっており,何も返ってないように思えます.
m2l

2021/06/13 06:20

大変失礼致しました。 大元のaxiosも返してあげるとどうでしょう? return axios .get(`${url}test/${text}`)
TAMANEKO

2021/06/13 06:49 編集

今試してみたところ,今度は何も実行されなくなりました. 開発者ツールで console.log は表示されておらず大本の画面の alert も出ませんでした. サーバのログにも実行の跡がありませんでした. 画面の挙動としては alert が出ずに更新されたようになります! ``` static getText(text) { console.log("START"); // 表示されるない ``` サーバ側はローカルで立ち上げて print してみるときちんと通って値を返しています. なので react 側の jsx か axios が原因なのではないかとあたりをつけています. reract のレンダリング的な部分か js の axios の非同期の理解が浅いのかなと疑っております.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問