DEV Community

kaede
kaede

Posted on • Updated on

Next 基礎 Part 02 -- axios で API を叩けるようにする。No 'Access-Control-Allow-Origin' エラーの解決。

why

前回の記事で Next.ts プロジェクトをテンプレで作った。
今回は API を呼べるようにする。

Axios 入れて useEffect で呼ぶだけでは叩けなかった。
6h ほどハマったので、解決策を記事にしておく。


axios のインストール

npm i axios
Enter fullscreen mode Exit fullscreen mode

axios を使うことで HTTP リクエストができる。


UseEffect について

初回起動時に API を叩くように。

https://masa-engineer-blog.com/react-hook-useeffect/

第 2 引数がないと初回のみ動く
第 2 引数があると第 2 引数の更新時のみ動く


axios.create で GET リクエストをする

Home で

  const axiosInstance = axios.create({
    baseURL: "http://localhost:8080",
    headers: {
      'Content-Type': 'application/json',
    },
  })
Enter fullscreen mode Exit fullscreen mode
  • ベースの URL
  • コンテンツタイプが JSON

ということを指定してインスタンスを作る

  const getHeardOn = async () => {
    console.log("getHeardOn");
    await axiosInstance
      .get(`/heard-on`)
      .then((response)=>{
        setHeardOn(()=> response.data)
      })
      .catch((e) =>{
        console.log(`Error: ${e}`);
      })
  }
Enter fullscreen mode Exit fullscreen mode

次にインスタンスを使って
/heard-on に GET リクエストをする。
/heard-one は person-api で作ったエンドポイント。


useEffect で初回ロード時に呼び出す

  useEffect(() => {
    console.log("loaded");
    getHeardOn()
    console.log(heardOn);

  })
Enter fullscreen mode Exit fullscreen mode

初回ロード時に getHeardOn を呼び出すようにする。

Access to XMLHttpRequest at 
'http://localhost:8080/heard-on' 
from origin 'http://localhost:3000' 
has been blocked by CORS policy: 

No 'Access-Control-Allow-Origin' header is present 
on the requested resource.
Enter fullscreen mode Exit fullscreen mode

localhost 3000 からのリクエストが
CORS によって弾かれた。

Access-Control-Allow-Origin
というヘッダーがリクエストのリソースに存在しない

とエラーが出た。

Access-Control-Allow-Origin をヘッダーに追加して送信に失敗

https://stackoverflow.com/questions/45975135/access-control-origin-header-error-using-axios

この記事を参考にして

  const axiosInstance = axios.create({
    baseURL: "http://localhost:8080",
    headers: {
      'Content-Type': 'application/json',
      "Access-Control-Allow-Origin": "*",
    },
  })
Enter fullscreen mode Exit fullscreen mode

Access-Control-Allow-Origin: *

アクセスを許可する元:全て
にしたヘッダーを作ってリクエストした。

Access to XMLHttpRequest 
at 
'http://localhost:8080/heard-on' 
from origin
'http://localhost:3000' 
has been blocked by CORS policy: 

Response to preflight request 
doesn't pass access control check: 

No 'Access-Control-Allow-Origin' header 
is present on the requested resource.
Enter fullscreen mode Exit fullscreen mode

https://qiita.com/kurab/items/84573b3092c8db4ba750#preflight-request-%E3%81%AE-ok-status-%E3%82%92%E8%BF%94%E3%81%99

kurab さんのにている記事を見つけたが少し違う。

やはり 'Access-Control-Allow-Origin' がついてないと怒られている。

axios インスタンスにつけるだけではダメなようだ。


next config の rewrite でローカルに送っている体にする

next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/(.*)',
        destination: 'http://localhost:8080',
      },
    ]
  },
};


module.exports = nextConfig
Enter fullscreen mode Exit fullscreen mode

これで baseURL なしで、
デフォルトの localhost 3000 に送るコードが
到着地の localhost8080 に書き換わって送信される。

index.tsx

  const axiosInstance = axios.create({
    // baseURL: "http://localhost:8080",
    headers: {
      'Content-Type': 'application/json',
    },
  })
Enter fullscreen mode Exit fullscreen mode

なので baseURL を外した。これで 8080 に送信できる。

実際に person-api と person-web を動かすと

Image description

上記のレスポンスで

これで解決した。


rewrite の詳細

https://nextjs-ja-translation-docs.vercel.app/docs/api-reference/next.config.js/rewrites

公式を見ると、
rewrite / source, destination は
proxy として mask するとある
/ へのリクエストを /about に変えて送るものだと解釈した。

なのでこの rewrite と proxy を使う。
localhost 3000 にリクエストさせるように見せる。
実際は localhost 8080 にリクエストさせる。

Next からは localhost 3000 の自分自身に送るように見える。
なので CORS エラーが出ない。

以上。

Top comments (0)