
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アニメで解説