エラー内容に持っていかれすぎて、基本を忘れないようにしようというお話です。
やったこと
下記のような、postをaxiosで実行する関数をReactで作り、コンポーネントで読み込んだ上でapiサーバーにpostを実行しました。
postすることでtopicが作られます。
同じページで追加されたコンテンツを表示したかったので、再読み込みをしようとしていました。
※useStateで既存ページにアイテムを追加しても良いけど、apiから返ってくる値の調整が面倒だったので、一旦これで試してた状態。
該当の関数。
export const createTopics = (title,body) => {
const target_URL = `${API_URL}/create`;
const res = axios//csrf保護の初期化
.get(API_SANCTUM_URL, { withCredentials: true })
.then((res) => {
axios.post(target_URL,
{title: title,body: body},
{headers:
{'Content-Type': 'multipart/form-data',},
withCredentials:true,
},
)
})
return res.data;
}
呼び出し元のコード。(formのsubmitをすると走るよ)
const submit = (data:FormInputs) => {
createTopics(data.Title,data.Body,data.Status,imgData)
window.location.reload()
}
事象
これを実行すると、コンソールにエラーが発生。
ページの再読み込みは実行されるが、topicが追加されていません。
なお、エラー内容は以下のものです。
Uncaught (in promise) Object { message: "Request aborted", name: "AxiosError",
code: "ECONNABORTED", config: {…}, request: XMLHttpRequest, stack: "" }
はまったポイント
このエラーで、なんらかの原因でaxiosのrequestが中断されてる。。。ということは想像できます。
また、状態としては、createTopicsが実行される前に再読み込みが実行された状態。
ここでひとまずなんで中断されたんだ?とググりました。あまりhitはしませんが、下記のissueが見つかりました。
axios本家のissueだ、これは何か重要な情報に違いない!と読み込みます。
buttonタグにtype = buttonをつけてみて、とかfirefoxでだけ起きるよ、とかあるけれど、
そもそもaxiosはpromiseを返すということを忘れていました。
解決。
呼び出し元でasync awaitつけてthenの中で実行してみました。
const submit = async (data:FormInputs) => {
await createTopics(data.Title,data.Body,data.Status,imgData).then(()=>{
window.location.reload();
})
}
ではなかった。呼び出しもとは最初の状態に戻して、
関数自体で行う必要があります。こうですね。
export const createTopics = (title,body) => {
const target_URL = `${API_URL}/create`;
const res = axios//csrf保護の初期化
.get(API_SANCTUM_URL, { withCredentials: true })
.then((res) => {
axios.post(target_URL,
{title: title,body: body},
{headers:
{'Content-Type': 'multipart/form-data',},
withCredentials:true,
},
).then(()=>{
window.location.reload();
})
})
return res.data;
}
これで、postがきちんと実行された上で、再読み込みが実行されました。
まとめ
createTopicsは非同期の処理なので、
1.axiosの処理が開始
2.1が終わる前に次の行でリダイレクト
の状態から、
1.axiosの処理が開始
2.1の処理の中で、リダイレクト
に変えた状態です。
エラーメッセージに引っ張られてaxiosの使い方、非同期の動きの基本を忘れていました!