[Next.js] Using axios to get data with SWR

programming
language

I will show you how to use axios to get data in Next.js SWR.

The API server is assumed to be Laravel.
We also assume that Laravel is using Eloquent’s API Resources when returning data.

Eloquent: API Resources - Laravel - The PHP Framework For Web Artisans

So, when you request article data, the data returned by the API server is as follows.

{
    "data": {
        "id": 1,
        "title": "title",
        ...
        "created_at": "2021-10-04T08:51:07.000000Z",
        "updated_at": "2021-10-04T08:51:08.000000Z"
    }
}

Getting data using axios with SWR

To use axios in SWR, set axios as the second argument of useSWR(), and SWR will fetch data using axios.

The code for SWR using axios is as follows.
It is assumed to get the article data.

import React, { useEffect } from "react";
import axios from "axios";
import useSWR from "swr";

export type Props = {
	query: { id: string };
};

export type fetchPostReturnType = {
	data: Post;
};

const PostContainer: React.FC<Props> = (props) => {
  const { data, error } = useSWR(
		`https://example.com/api/v1/post/${props.query.id}`,
		axios
	);

  return (
    ...
  );
}

The data we were able to obtain is as follows.

{
    "data": {
        "data": {
            "id": 1,
            "title": "タイトル",
            ...
            "created_at": "2021-10-04T08:51:07.000000Z",
            "updated_at": "2021-10-04T08:51:08.000000Z"
        }
    },
    "status": 200,
    "statusText": "OK",
    "headers": {
        ...
    },
    "config": {
        "url": "http://localhost:8000/api/v1/post/10",
        ...
    },
    "request": {}
}

As it is, it is not as easy to use as the following.

  • A lot of unnecessary data
  • Deep to article data
  • The variable name in which the retrieved data is stored is “data”, which is not readable.

You don’t want to do the following to access the title of the article,

const title = data.data.data.title;

and I don’t want to bother extracting the article data for better readability as follows.

const post = data.data.data;

Try to return data that is easy to handle.

It would have been nice to be able to easily use axios to get data just by putting it in the second argument of useSWR(), but it returned unusable data as shown below.

  • A lot of unnecessary data
  • Deep to article data
  • The variable name in which the retrieved data is stored is “data”, which is not readable.

I want the data returned by useSWR() to be usable at the time, so I improved the code as follows. Typescript, of course.

import React, { useEffect } from "react";
import axios from "axios";
import useSWR from "swr";

export type Props = {
	query: { id: string };
};

export type fetchPostReturnType = {
	data: {
    id: number;
    title: string;
    ...
  };
};

const PostContainer: React.FC<Props> = (props) => {
  const fetcher = (url: string): Promise<fetchPostReturnType> =>
		axios(url).then((res) => res.data);

  const { data: post, error } = useSWR(
		`https://example.com/api/v1/post/${props.query.id}`,
		fetcher
	);

  return (
    ...
  );
}

The name of the variable that stores the data returned by useSWR() is changed to post instead of data.
And the data in the post is as follows.

{
    "data": {
        "id": 1,
        "title": "タイトル",
        ...
        "created_at": "2021-10-04T08:51:07.000000Z",
        "updated_at": "2021-10-04T08:51:08.000000Z"
    }
}

The article data is now much cleaner and easier to handle.

When retrieving the article title, you can now get it as follows

const title = post.data.title;

Conclusion.

The code has been improved to return simple and readable data as shown below.

  • Data is simple
  • Shallow to article data
  • The variable name where the retrieved article data is stored is post, which has good readability

Also, by changing the variable that stores the return value of useSWR(), it is now possible to use multiple useSWR() to get post and comments data, as shown below.

import React, { useEffect } from "react";
import axios from "axios";
import useSWR from "swr";

export type Props = {
	query: { id: string };
};

export type fetchPostReturnType = {
	data: {
    id: number;
    title: string;
    ...
  };
};

export type fetchCommentsReturnType = {
	data: {
    id: number;
    comment: string;
    ...
  }[];
};

const PostContainer: React.FC<Props> = (props) => {
  // 記事データを取得
  const postFetcher = (url: string): Promise<fetchPostReturnType> =>
		axios(url).then((res) => res.data);
  const { data: post, error: postError } = useSWR(
		`https://example.com/api/v1/post/${props.query.id}`,
		postFetcher
	);
  // コメントデータを取得
  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
	);

  return (
    ...
  );
}
タイトルとURLをコピーしました