ウェブフロント
- angular
- corewebvitals
- editorconfig
- gatsby
- hls
- html
- javascript
querySelectorAllで取得した要素は配列ではないらしい
JavaScript 配列内のオブジェクトの更新ってどうする?
デバッグ関数とかnullチェック関数をutil/index.tsにおいとけば楽なことに今頃気づいた。
ブラウザからジャイロセンサーを使ってみる
JS 画像のアップロード、プレビュー機能を実装
「数値から各桁の値を取り出す処理」って言われたら数学的な処理が一番に思い浮かぶけど、JSならそんなことなかった。
Callback時代の関数をPromise化する
個人的実装されてほしいECMA Script Proposal
JavaScriptのprototypeを使う
音声をなみなみさせる
AudioWorkletとAudioWorkletProcessorを使って音声のビジュアライゼーション
- next
- nuxt
- playwright
- prettier
- react
- reactnative
- tensorflowjs
- tools
- typescript
- wasm
- websocket
- ポエム
- 開発環境
サーバー
その他
Next.js 北九州市のイベント情報を取得する
はじめに
Next.jsを使って北九州市のイベント情報サイトを作成するチュートリアルです.
Next.jsを使ってサーバーから外部のサイトにアクセスすることでCORS対策にもなります.
Next.jsを使ってサーバーから外部のサイトにアクセスすることでCORS対策にもなります.
完成品
サイトURL
https://kitakyushu-event-site.fukekazki.now.sh/
リポジトリ
https://github.com/FukeKazki/Kitakyushu-event-site
準備
プロジェクトの作成
$ 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にコードを追加します.
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文を使ってエラーが起きた場合の対処をしています.
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を使ってループを回して表示しています.
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を書く記法で良いというところです.
利点は記述をキャメルケースにしなくてよく, 通常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を使ったデプロイも超ラクなのでおすすめです.
今回取得してきた北九州市のイベント情報もパブリックに公開しているものではなく, 自分で探しだしたやつなので, フロントからデータを取得しようとするとCORSで弾かれます.
こういうときにSSRを使えば(用途が合ってるのかは置いといて)CORSをくぐり抜けてデータの取得ができます(ニアッ)
またNowを使ったデプロイも超ラクなのでおすすめです.
Thanks you for reading.