useSWR()を使ってデータを取得するには以下の方法で取得できました。
const commentsFetcher = (url: string): Promise<fetchCommentsReturnType> =>
axios(url).then((res) => res.data);
const { data: comments, error:commentsError } = useSWR(
`https://example.com/api/v1/post/${props.query.id}/comments`,
commentsFetcher
);
useSWR()を使ってデータの取得方法がわからない方は「【Next.js】axiosを使ってSWRで取得する」を参照してください。
同じような方法でPOSTすることはできますが、その方法はオススメできません。
SWR公式ページにも「データ取得のための React Hooks ライブラリ」と書かれています。
SWRはデータ取得専用のReact Hooks ライブラリです。
この記事ではuseSWR()を使ってPOSTする方法とそれがオススメできない理由とオススメのPOSTの方法をご紹介します。
useSWR()を使ってPOST
useSWR()を使って以下のようにポストできますが、この方法はオススメできません。
なぜならこの方法ではSWRの素晴らしい機能が使えないからです。
const fetcher = params => url => post(url, params)
const { data, error } = useSWR(
`https://example.com/api/v1/post/${props.query.id}/comments`,
fetcher({comment: val})
);
SWRはデータ取得専用だからPOSTするにはaxiosを使う
冒頭にも紹介しましたが、SWRはデータ取得専用なのでPOSTするにはおとなしくaxiosなどを使いましょう。
こちらの記事がわかりやすいと思います。
https://www.sukerou.com/2019/05/axios.html
また、Next.jsとAPIサーバーの通信はこちらの書籍が参考になります。
データを再取得はuseSWR()のmutate()を使う
useSWR()の返り値にはmutate()があります。
const commentsFetcher = (url: string): Promise<fetchCommentsReturnType> =>
axios(url).then((res) => res.data);
const { data: comments, error:commentsError, mutate } = useSWR(
`https://example.com/api/v1/post/${props.query.id}/comments`,
commentsFetcher
);
mutate()を使ってデータを更新することでSWRの以下の機能が利用できます。
- stale-while-revalidate(SWR)
- 再検証
- ポーリングによるデータの自動再フェッチ
- 重複排除
- データのキャッシュ
- And lot more.
mutate()を使ったデータの更新は以下の順序で行います。
- axiosやfetchでPOSTする
- mutate()を使ってデータを更新する
mutate()を使ったデータの更新のサンプルコードは以下の通りです。
POSTはaxiosでもfetchでもいいのですが、今回はaxiosを使用しています。
import React, { useEffect } from "react";
import axios from "axios";
import useSWR from "swr";
export type Props = {
query: { id: string };
};
...
export type fetchCommentsReturnType = {
data: {
id: number;
comment: string;
...
}[];
};
const PostContainer: React.FC<Props> = (props) => {
...
// コメントデータを取得
const commentsFetcher = (url: string): Promise<fetchCommentsReturnType> =>
axios(url).then((res) => res.data);
const { data: comments, error:commentsError, mutate } = useSWR(
`https://example.com/api/v1/post/${props.query.id}/comments`,
commentsFetcher
);
const handleOnSubmit = async (e: React.SyntheticEvent): Promise<void> => {
e.preventDefault();
const target = e.target as typeof e.target & {
comment: { value: string };
};
const res = await axios.post(
`https://example.com/api/v1/post/${props.query.id}/comments`,
{ comment: target.comment.value }
);
let newComments = (comments as fetchCommentReturnType).data;
newComments.push(res.data.data);
commentsMutate({ ...comments, data: newComments });
};
return (
<form
...
onSubmit={(e) => handleOnSubmit(e)}
>
...
</form>
);
}
mutate()を使ったデータの更新方法
mutate()の書式は以下のとおりです。
(alias) mutate(
key: keyInterface,
data?: any,
shouldRevalidate?: boolean | undefined
): Promise<any>
各引数の渡すデータは以下のとおりです。
- 第1引数(key): URLを指定する
- 第2引数(data): データ
- 第3引数: (shouldRevalidate): 再検証の実行
mutate()を使ったデータの更新方法はいくつかあります。
先程のサンプルコードではuseSWR()の返り値のmutate()を使っていたので第1引数のkeyを省略できました。
以下のようにデータを更新しました。
const { data, mutate } = useSWR('/api/user', fetcher)
...
mutate(newUser);
// 再検証なし
// mutate(newUser, false);
しかし、mutate()は上記の書式の通りkeyを指定してデータを更新することもできます。
import React, { useEffect } from "react";
import axios from "axios";
import useSWR, { useSWRConfig } from 'swr'
export type Props = {
query: { id: string };
};
...
export type fetchCommentsReturnType = {
data: {
id: number;
comment: string;
...
}[];
};
const PostContainer: React.FC<Props> = (props) => {
const { mutate } = useSWRConfig()
...
// コメントデータを取得
const commentsFetcher = (url: string): Promise<fetchCommentsReturnType> =>
axios(url).then((res) => res.data);
const { data: comments, error:commentsError } = useSWR(
`https://example.com/api/v1/post/${props.query.id}/comments`,
commentsFetcher
);
const handleOnSubmit = async (e: React.SyntheticEvent): Promise<void> => {
e.preventDefault();
const target = e.target as typeof e.target & {
comment: { value: string };
};
const res = await axios.post(
`https://example.com/api/v1/post/${props.query.id}/comments`,
{ comment: target.comment.value }
);
let newComments = (comments as fetchCommentReturnType).data;
newComments.push(res.data.data);
mutate(
`https://example.com/api/v1/post/${props.query.id}/comments`,
{ ...data, name: newName },
false
);
};
return (
<form
...
onSubmit={(e) => handleOnSubmit(e)}
>
...
</form>
);
}
https://github.com/vercel/swr/issues/93#issuecomment-551110903
コメント