Next.js(React)+Go
で個人開発をしていて、FetchAPIを利用してGo
でローカル環境にたてたAPIをNext.js
で呼び出す際に、値が取れずにはまりました。
今回はどうやって解消したのか記事にしました。
今回発生したエラー
Next.js
でfetch
を使ってPOSTした際に、以下のようなエラーが発生。
Error serializing `.postData` returned from `getServerSideProps` in "/posts/get-api". Reason: `object` ("[object Promise]") cannot be serialized as JSON. Please only return JSON serializable data types.
ようわからんけど、APIから値が取れてないみたいでした。
Next.js
からfetch
する際のコードは以下のようにしていました。
export const getServerSideProps: GetServerSideProps = async () => {
const url = "http://localhost:8080/login"; ← APIはローカルの8080番ポートにたてていました。
let postData = {};
await fetch(url, {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/json charset=utf-8",
},
body: JSON.stringify({ username: "yagiyu", password: "miran" }),
}).then(function (response) {
console.log(response);
postData = response.json();
});
return {
props: {
postData,
},
};
};
また、上記を実行した時のレスポンスが以下で、APIと通信はできたが、値を取れませんでした。
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: {
body: PassThrough {
_readableState: [ReadableState],
readable: true,
_events: [Object: null prototype],
_eventsCount: 2,
_maxListeners: undefined,
_writableState: [WritableState],
writable: false,
allowHalfOpen: true,
_transformState: [Object],
[Symbol(kCapture)]: false
},
disturbed: false,
error: null
},
[Symbol(Response internals)]: {
url: 'http://localhost:8080/login',
status: 200,
statusText: 'OK',
headers: Headers { [Symbol(map)]: [Object: null prototype] },
counter: 0
}
}
ターミナルからcurl
を実行すると、以下のように成功していました。
$ curl -XPOST -d'{"username": "yagiyu", "password": "miran"}' localhost:8080/login
{"user":{"firstName":"yu","lastName":"yagishita","username":"yagiyu"}}
解消方法
getServerSideProps
の関数内で、fetch
で非同期処理をしていたコードのthen
をやめて、await
にすることで値を取得して、return
できました。
export const getServerSideProps: GetServerSideProps = async () => {
const url = "http://localhost:8080/login";
const response = await fetch(url, {
method: "POST",
cache: "no-cache",
headers: {
"Content-Type": "application/json charset=utf-8",
},
body: JSON.stringify({ username: "yagiyu", password: "miran" }),
});
const postData = await response.json();
return {
props: {
postData,
},
};
};
エラー原因
JavaScript
の非同期処理Promise
, Async
, Await
について理解していなかったことが原因でした。
then
で非同期処理の結果を得ようとする場合、先にreturn
が実行されてしまい、空のpostData
が渡されていました。これをawait
に変えることで、非同期処理が完了するのを待ってからreturn
されるようになり、エラーを解消できました。
JavaScript
の非同期処理をしっかりと理解できていないので、今後もコードをたくさん書いて覚えていきます。
この記事がわかりやすかったので、是非読んでみてください。
JavaScriptの非同期処理Promise、AsyncとAwaitの仕組みをGIFアニメで解説