はじめに
こんにちは!WEBエンジニア転職目指しているK.Yです!
今回は、APIでデータを取得して表示させる内容となります。
以下の記事は、手書きでデータを取得した内容となります!
良かったらこちらも読んでいただけると嬉しいです!
Reactの基本的な機能や特徴について記述しています!
前回の記事と重複している部分は省略しております!
対象者
・ React初心者
・ フロントエンドに興味がある人
バージョン
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1"
JavaScript ES6以降
コード
PostsList
import React, { useEffect, useState } from 'react'
import './App.css'
import { Link } from 'react-router-dom';
const PostsList = () => {
const formatDate = (dateString) => {
const date = new Date(dateString);
const options = { year: 'numeric', month: 'numeric', day: 'numeric' };
return date.toLocaleDateString('ja-JP', options);
};
const [posts, setPosts] = useState({ articles: [] });
const [loading, setLoading] = useState(true); // ローディング状態を追加
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("https://1hmfpsvto6.execute-api.ap-northeast-1.amazonaws.com/dev/posts");
const data = await response.json();
setPosts( data );
} finally {
setLoading(false); // データ取得が完了したらローディングを終了
}
};
fetchData();
}, []);
if (loading) {
return <div>Loading...</div>; // ローディング中の表示
}
return (
<div className="App">
<header className="header-App">
<Link className="link" to="/">Blog</Link>
<Link className="link" to="/">お問い合わせ</Link>
</header>
{
Array.isArray(posts.posts) && posts.posts.map(article => (
<div key={article.id} className="posts-info">
<ul >
<li>
<Link to={`/post/${article.id}`}>
<div className="date">{formatDate(article.createdAt)}</div>
<div className="programming-language">{article.categories.map((category, idx) => (
<span key={idx} className="category-box">{category}</span>
))}</div>
<div className="title">{article.title}</div>
<div className="content" dangerouslySetInnerHTML={{ __html: article.content }}>
</div>
</Link>
</li>
</ul>
</div>
))}
</div>
);
}
export default PostsList;
DetailsPage
const { id } = useParams();
const formatDate = (dateString) => {
const date = new Date(dateString);
const options = { year: 'numeric', month: 'numeric', day: 'numeric' };
return date.toLocaleDateString('ja-JP', options);
}
const [detailsData, setDetailsData] = useState();
const [loading, setLoading] = useState(true); // ローディング状態を追加
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://1hmfpsvto6.execute-api.ap-northeast-1.amazonaws.com/dev/posts/${id}`);
const result = await response.json();
setDetailsData(result.post);
} finally {
setLoading(false); // データ取得が完了したらローディングを終了
}
};
fetchData();
}, [id]);
if (loading) {
return <div>Loading...</div>; // ローディング中の表示
}
if (!detailsData) return <div>投稿が見つかりません</div>;
return (
<div className='App'>
<header className="header-App">
<Link to="/" className="link">Blog</Link>
<Link to="/" className="link" >お問い合わせ</Link>
</header>
<div style={{ border: 'none' }} className="posts-info">
<ul>
<li key={detailsData.id}>
<div><img src={detailsData.thumbnailUrl} alt="img" /></div>
<div className="date">{formatDate(detailsData.createdAt)}</div>
<div className="programming-language">
{detailsData.categories.map((category, idx) => (
<span key={idx} className="category-box">{category}</span>
))}
</div>
<div className="title">{detailsData.title}</div>
<div style={{ display: 'block' }} className="content" dangerouslySetInnerHTML={{ __html: detailsData.content }}></div>
</li>
</ul>
</div>
</div>
);
}
export default DetailsPage;
API
APIとは、ソフトウェアアプリケーションが互いにやり取りを行うための仕組みです。
フロントエンド、バックエンドの連携において重要な役割を果たします。
APIはHTTPなどのプロトコルを用いて、リクエストやレスポンスのやり取りを行います。
リクエストには、データの取得や登録・削除・更新などの操作を支持する情報が含まれていて、
レスポンスは、データやエラーメッセージ’などの情報が含まれています。
PostsList(記事一覧ページ)
PostsList
import React, { useEffect, useState } from 'react'
import './App.css'
import { Link } from 'react-router-dom';
const PostsList = () => {
const formatDate = (dateString) => {
const date = new Date(dateString);
const options = { year: 'numeric', month: 'numeric', day: 'numeric' };
return date.toLocaleDateString('ja-JP', options);
};
const [posts, setPosts] = useState({ articles: [] });
const [loading, setLoading] = useState(true); // ローディング状態を追加
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("https://1hmfpsvto6.execute-api.ap-northeast-1.amazonaws.com/dev/posts");
const data = await response.json();
setPosts( data );
} finally {
setLoading(false); // データ取得が完了したらローディングを終了
}
};
fetchData();
}, []);
if (loading) {
return <div>Loading...</div>; // ローディング中の表示
}
return (
<div className="App">
<header className="header-App">
<Link className="link" to="/">Blog</Link>
<Link className="link" to="/">お問い合わせ</Link>
</header>
{
Array.isArray(posts.posts) && posts.posts.map(article => (
<div key={article.id} className="posts-info">
<ul >
<li>
<Link to={`/post/${article.id}`}>
<div className="date">{formatDate(article.createdAt)}</div>
<div className="programming-language">{article.categories.map((category, idx) => (
<span key={idx} className="category-box">{category}</span>
))}</div>
<div className="title">{article.title}</div>
<div className="content" dangerouslySetInnerHTML={{ __html: article.content }}>
</div>
</Link>
</li>
</ul>
</div>
))}
</div>
);
}
export default PostsList;
ステートの設定
const [posts, setPosts] = useState({ articles: [] });
const [loading, setLoading] = useState(true); // ローディング状態を追加
・useState
を使って、ステートを定義。
posts
は、APIから取得したデータを格納するためのステートです。
初期値は{ articles: [] }
(空の配列を含むオブジェクト)です。
・setPosts
は、posts
ステートを更新するための関数です。
・loading
は、データがロード中であるかどうかを示すブール値のステートです。
初期値は、true
・setLoading
は、loading
を更新するための関数です。
データ取得(useEffectフック)
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch("https://1hmfpsvto6.execute-api.ap-northeast-1.amazonaws.com/dev/posts");
const data = await response.json();
setPosts(data);
} finally {
setLoading(false); // データ取得が完了したらローディングを終了
}
};
fetchData();
}, []);
・useEffect
を使って、副作用(この場合はデータ取得)を実行します。
useEffect
の第二引数に空の配列[]
を渡すことで、ページ読み込み時にデータを取得したい時に、用いる手法です。
・fetchData
は非同期関数で、APIからデータを取得。
・fetch
関数を使って、指定されたURLからデータを取得。
・await
を使って、fetch
関数が完了するのを待つ」。
・response.json()
を使って、取得したデータをJSON形式に変換します。
・setPosts(data)
を使って、取得したデータをposts
ステートに保存。
・loading
ステートをfalse
に設定します。
・useEffect
の中で、fetchData
関数を呼び出して、データ取得を開始します。
・loading
ステートがtrue
の間は、"Loading..."というメッセージを表示します。
データ取得が完了してloading
ステートがfalse
になると、この部分はスキップされ、次の部分(投稿リストの表示)が実行。
DetailsPage.js (記事詳細ページ)
DetailsPage
const { id } = useParams();
const formatDate = (dateString) => {
const date = new Date(dateString);
const options = { year: 'numeric', month: 'numeric', day: 'numeric' };
return date.toLocaleDateString('ja-JP', options);
}
const [detailsData, setDetailsData] = useState();
const [loading, setLoading] = useState(true); // ローディング状態を追加
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://1hmfpsvto6.execute-api.ap-northeast-1.amazonaws.com/dev/posts/${id}`);
const result = await response.json();
setDetailsData(result.post);
} finally {
setLoading(false); // データ取得が完了したらローディングを終了
}
};
fetchData();
}, [id]);
if (loading) {
return <div>Loading...</div>; // ローディング中の表示
}
if (!detailsData) return <div>投稿が見つかりません</div>;
return (
<div className='App'>
<header className="header-App">
<Link to="/" className="link">Blog</Link>
<Link to="/" className="link" >お問い合わせ</Link>
</header>
<div style={{ border: 'none' }} className="posts-info">
<ul>
<li key={detailsData.id}>
<div><img src={detailsData.thumbnailUrl} alt="img" /></div>
<div className="date">{formatDate(detailsData.createdAt)}</div>
<div className="programming-language">
{detailsData.categories.map((category, idx) => (
<span key={idx} className="category-box">{category}</span>
))}
</div>
<div className="title">{detailsData.title}</div>
<div style={{ display: 'block' }} className="content" dangerouslySetInnerHTML={{ __html: detailsData.content }}></div>
</li>
</ul>
</div>
</div>
);
}
export default DetailsPage;
データ取得(useEffectフック)
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(`https://1hmfpsvto6.execute-api.ap-northeast-1.amazonaws.com/dev/posts/${id}`);
const result = await response.json();
setDetailsData(result.post);
} finally {
setLoading(false); // データ取得が完了したらローディングを終了
}
};
fetchData();
}, [id]);
・useEffect
の第二引数に[id]
を渡すことで、id
が変わるたびにこの副作用が再実行されます。
・ try
ブロック内で、データの取得と処理を行います。
・finally
ブロックで、データ取得が完了したら(成功しても失敗しても)loading
ステートをfalse
に設定します。
ポイント
・副作用の管理
とAPIを呼び出す処理
useEffect
フックを使って、API
データを取得などの副作用を管理。
・非同期処理 async
/await
非同期処理は、時間のかかる操作(例えば、ネットワークリクエストやファイルの読み書きなど)をブロックせずに実行するために使用されます。JavaScriptでは、非同期処理を行うためにasync
/awaitやPromise
を使う。
終わり
今回は、APIでデータ取得を実装してみました!
少しでもこの記事がお役に立てれば幸いです!
次回は、問い合わせフォームの作成となります。
お楽しみに!