Next.js 北九州市のイベント情報を取得する
- Next.js 北九州市のイベント情報を取得する
- Next.js × now がやばい
- 競プロ日記 ABC15
- 競プロ日記 ABC159
- Kaggle 住宅価格予測 単回帰分析してみる
- 単回帰分析のFlow
- React Native Styleをいい感じに
- React Movie Search を TS で.
- useRefの使い方がわからん
- Heroku PostgreSQL の使い方
- ラズパイとLEDマトリクスパネルで遊ぶ
- querySelectorAllで取得した要素は配列ではないらしい
- React HookでTodoアプリを作る
- Kaggle 住宅価格予測 重回帰分析してみる
- Kaggle 住宅価格予測 多項式回帰してみる
- Webフロントのすべて
- 新しいMacBook Airが届いた!
- 日向坂46のニュースをスクレイピング
- イコラブのニュースをスクレイピングする!
- 推しのブログをスクレイピング
はじめに
Next.jsを使って北九州市のイベント情報サイトを作成するチュートリアルです.
Next.jsを使ってサーバーから外部のサイトにアクセスすることでCORS対策にもなります.
完成品
準備
プロジェクトの作成
$ yarn create next-app
ライブラリの導入
# API通信ライブラリ
$ yarn add axios
# CSSライブラリ
$ yarn add styled-components
$ yarn add @material-ui/core
# TypeScriptライブラリ
$ yarn add @types/node @types/react typescript
作成
pages/index.tsx
import React from "react";
import Head from "next/head";
import { NextPage } from "next";
import CssBaseline from "@material-ui/core/CssBaseline";
import Container from "@material-ui/core/Container";
const Home: NextPage = () => {
return (
<React.Fragment>
<Head>
<title>北九州イベントサイト</title>
</Head>
<CssBaseline />
<main>
<Container maxWidth="lg">
<h1>Hello Next.js</h1>
</Container>
</main>
</React.Fragment>
);
};
export default Home;
index.jsのファイル名をindex.tsxに変えるのを忘れないようにしましょう.
サーバーの起動
$ yarn run dev
コマンドを実行するとtypescript用のconfigファイルが自動生成されて, 3000番で実行されます.
北九州市のサイトからイベント情報を取得してくる
Next.jsのgetInitialPropsという関数を使ってサーバーからデータを取得します.
pages/index.tsxにコードを追加します.
// 略
import axios from "axios"; // 追加
const Home: NextPage = () => {
// 略
};
// 追加
Home.getInitialProps = async () => {
try {
const res = await axios.get(
"https://www.city.kitakyushu.lg.jp/cgi-bin/event/api.cgi",
);
console.log(res.data);
return res.data;
} catch (err) {
return err;
}
};
export default Home;
ターミナル画面にイベント情報が表示されます.
getInitialPropsはサーバーでHTMLが生成される前に実行されます.
axios.get()で引数のURLへGetリクエストを送りデータが帰ってくるまでawaitを使って待ちます.
データがきたらreturnでデータの中身をHomeコンポーネントへ返します.
また, try catch文を使ってエラーが起きた場合の対処をしています.
画面に表示
// import文 略
type event = {
event_name: string;
ent_wday: string;
ctg1: string;
pc_flag: string;
place: string;
begin_date: string;
begin_wday: string;
description: string;
disp_flag: string;
Area: string;
end_data: string;
url: string;
};
type HomeProps = {
events: event[];
};
const Home: NextPage<HomeProps> = ({ events }) => {
return (
<React.Fragment>
// 略
<main>
<Container maxWidth="lg">
{events.map((event, index) => (
<div>
<h2>{event.event_name}</h2>
<p>{event.description}</p>
</div>
))}
</Container>
</main>
</React.Fragment>
);
};
// 略
せっかくtypescriptを使うのでtypeを使ってイベントの型を定義しています.
HomePropsの型はeventの配列です.
配列はmapを使ってループを回して表示しています.
見た目をいい感じに
// 追加
import styled from "styled-components";
import Box from "@material-ui/core/Box";
const Home: NextPage<HomeProps> = ({ events }) => {
return (
<React.Fragment>
// 略
<main>
<Container maxWidth="lg">
{events.map((event, index) => (
// 書き換え
<EventCard>
<h2>{event.event_name}</h2>
<p>{event.description}</p>
</EventCard>
))}
</Container>
</main>
</React.Fragment>
);
};
// 追加
const EventCard = styled(Box)`
border: 1px solid #4d4d4d;
padding: 1em 2em;
margin-top: 1em;
border-radius: 16px;
`;
こんな感じに表示がされれば完成です.
styled-componentを使って, CSSを書いています.
利点は記述をキャメルケースにしなくてよく, 通常CSSを書く記法で良いというところです.
デプロイ
NowというPaaSを使ってデプロイします.
# nowコマンドのインストール
$ npm i -g now
# nowのアカウントを作成・ログイン
$ now login
# デプロイコマンド
$ now
最終的なコード
import React from "react";
import Head from "next/head";
import { NextPage } from "next";
import axios from "axios";
import styled from "styled-components";
import CssBaseline from "@material-ui/core/CssBaseline";
import Container from "@material-ui/core/Container";
import Box from "@material-ui/core/Box";
type event = {
event_name: string;
ent_wday: string;
ctg1: string;
pc_flag: string;
place: string;
begin_date: string;
begin_wday: string;
description: string;
disp_flag: string;
Area: string;
end_data: string;
url: string;
};
type HomeProps = {
events: event[];
};
const Home: NextPage<HomeProps> = ({ events }) => {
return (
<React.Fragment>
<Head>
<title>北九州イベントサイト</title>
</Head>
<CssBaseline />
<main>
<Container maxWidth="lg">
{events.map((event, index) => (
<EventCard>
<h2>{event.event_name}</h2>
<p>{event.description}</p>
</EventCard>
))}
</Container>
</main>
</React.Fragment>
);
};
Home.getInitialProps = async () => {
try {
const res = await axios.get(
"https://www.city.kitakyushu.lg.jp/cgi-bin/event/api.cgi",
);
return res.data;
} catch (err) {
return err;
}
};
const EventCard = styled(Box)`
border: 1px solid #4d4d4d;
padding: 1em 2em;
margin-top: 1em;
border-radius: 16px;
`;
export default Home;
おわりに
データの取得 => 表示 が自由自在にできるようになればもう最強です(
今回取得してきた北九州市のイベント情報もパブリックに公開しているものではなく, 自分で探しだしたやつなので,
フロントからデータを取得しようとするとCORSで弾かれます.
こういうときにSSRを使えば(用途が合ってるのかは置いといて)CORSをくぐり抜けてデータの取得ができます(ニアッ)
またNowを使ったデプロイも超ラクなのでおすすめです.