hacca8

ReactでAPIを使って動的にページを表示する

Reactでアプリを作成する際、APIを利用してコンテンツを動的に表示させることが多いかと思います。
今回は簡単に、動的にデータの取得と表示する流れを確認します。ブログの雛形のような構成で作成していきます。

  • パッケージ
"axios": "^1.1.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.4.2",
"typescript": "^4.8.4",

ルーティングを設定するApp.tsxから順に確認します。

App.tsx

import React from 'react'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import Notes from './Notes'
import Note from './Note'

const App = () => (
  <BrowserRouter>
    <h1>Notes</h1>
    <Routes>
      <Route path='/' element={<Notes />} />
      <Route path=':slug' element={<Note />} />
    </Routes>
  </BrowserRouter>
)

export default App

ルーティングにはreact-router-domを利用します。基本的な使い方についてはこちらの記事を参照ください。

react-router-domでルーティング

<Notes />に記事一覧と、<Note />に記事内容を表示するよう設定していきます。ファイルは全て同階層に設置しています。

.
├── App.tsx
├── Note.tsx
├── Notes.tsx
├── index.tsx
└── types.ts

index.tsxはApp.tsxを表示しているだけです。

types.ts

export type NoteProps = {
  id?: string
  title?: string
  body?: string
}

記事データ用に型ファイルを用意します。今回は確認のため最低限の設定です。

Notes.tsx

import React from 'react'
import { useEffect, useState } from 'react'
import { Link } from 'react-router-dom'
import axios from 'axios'
import { NoteProps } from './types'

const Notes = () => {
  const [notes, setNotes] = useState([])

  useEffect(() => {
    (async () => {
      const res = await axios.get('https://jsonplaceholder.typicode.com/posts')
      setNotes(res.data)
    })()
  }, [])

  return (
    <ul>
      {notes.map((value: NoteProps) => (
        <li key={value.id}>
          {value.id}          <Link to={`${value.id}`}>
            {value.title}
          </Link>
        </li>
      ))}
    </ul>
  )
}

export default Notes

useStateはデータをnotesに格納するよう設定しています。
useEffectでデータを取得し、setNotesでnotesにデータを格納しています。また、非同期処理するため関数でラップします。useEffectについてはこちらの記事を参照ください。

useEffectフックについて

データの取得はAPIの動作確認できるサービスJSONPlaceholderを利用しています。フェッチは個人的によく利用するaxiosを使用しています。
notesで取得した記事データをreturn内のmapでLinkタグに設定しています。以上で、記事一覧のリンクが表示されます。

Note.tsx

import React from 'react'
import { useEffect, useState } from 'react'
import { Link, useParams } from 'react-router-dom'
import axios from 'axios'
import { NoteProps } from './types'

const Note = () => {
  const slug = useParams().slug
  const [note, setNote] = useState<NoteProps>({})

  useEffect(() => {
    (async () => {
      const res = await axios.get(`https://jsonplaceholder.typicode.com/posts/${slug}`)
      setNote(res.data)
    })()
  }, [])

  return (
    <>
      <div>ID: {note.id}</div>
      <h2>{note.title}</h2>
      <div>{note.body}</div>
      <Link to='../'>記事一覧へ</Link>
    </>
  )
}

export default Note

Notesの記事一覧からのリンクで記事IDを読み取り、IDに該当する記事データをAPIで取得します。
useParams:slugを受け取ります。useEffect内でslugを使いAPIサーバーのURLを作成しています。作成したURLより記事のコンテンツをnoteに格納し、ページに表示しています。
以上で記事の表示が確認できます。indexページから各記事へ遷移し、それぞれ違ったコンテンツが表示できるのが確認できます。

PS

APIを利用して動的なページ表示ができました。
本来はaxiosのエラー対応が必要だったり、詳細な型定義を行ったり、ページ内でさらにデータフェッチしたりと、もっと複雑になると思いますが、ひとまず簡単にReactでのAPI利用の流れを確認しました。