ReactとJavaScriptで記事一覧ページを作ってみた！その1

# はじめに
こんにちは！　WEBエンジニア転職目指しているK.Yです！
コメントいただけると嬉しです:sunglasses:

ReactとJavaScriptを使って、簡単なブログを作ってみました！
振り返りという意味で、Qiitaに残そうと思います。

以下、完成したブログです！

![fuga.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719491/5976f5e9-79c3-b2c2-ef39-a74ff8f4958c.gif)

段階に分けて記事を書こうと思います！
今回は、ホーム画面部分のアウトプット内容となります！


## 対象者
・　React初心者
・　フロントエンドに興味がある人

## バージョン
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.23.1"

JavaScript　ES6以降

記法: ほげほげ[^1]


## コード
``` javascript
    App.js
    
    import React from 'react'
    import './App.css'
    
    
    const PostsList = ({ src }) => {
    
      const formatDate = (dateString) => {
        const date = new Date(dateString);
    
        const options = { year: 'numeric', month: 'numeric', day: 'numeric' };
    return date.toLocaleDateString('ja-JP', options);
  }

  return (
    <div className="App">
      <header className="header-App">
        <a className="link" href='/'>Blog</a>
        <a className="link" href='/'>お問い合わせ</a>
      </header>

      {
        src.map((elem, index) => (
          <div key={index} className="posts-info">
            <ul >
              <li>
                <a href='/'>
                  <div className="date">{formatDate(elem.createdAt)}</div>
                  <div className="programming-language">{elem.categories.map((category, idx) => (
                    <span key={idx} className="category-box">{category}</span>
                  ))}</div>
                  <div className="title">{elem.title}</div>
                  <div className="content" dangerouslySetInnerHTML={{ __html: elem.content }}>
                  </div>
                </a>
              </li>
            </ul>
          </div>
        ))}
    </div>
    )}
    export default PostsList;
```

``` javascript
index.js

import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { posts } from './data/posts';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App src={posts}/>
  </React.StrictMode>
);
```

```javascript
posts.js

export const posts = [
  {
    id: 1,
    title: 'APIで取得した記事タイトル１',
    thumbnailUrl: 'https://placehold.jp/800x400.png',
    createdAt: '2023-09-11T09:00:00.000Z',
    categories: ['React', 'TypeScript'],
    content: `
    本文です。本文です。本文です。本文です。本文です。本文です。<br/>本文です。本文です。本文です。本文です。本文です。<br/><br/>本文です。本文です。本文です。本文です。本文です。本文です。本文です。本文です。本文です。<br/><br/><br/>本文です。本文です。本文です。本文です。本文です。本文です。<br/>`,
  },
  {
    id: 2,
    title: 'APIで取得した記事タイトル２',
    thumbnailUrl: 'https://placehold.jp/800x400.png',
    createdAt: '2023-09-10T09:00:00.000Z',
    categories: ['HTML', 'CSS'],
    content: `
    本文です。本文です。本文です。本文です。本文です。本文です。<br/>本文です。本文です。本文です。本文です。本文です。<br/><br/>本文です。本文です。本文です。本文です。本文です。本文です。本文です。本文です。本文です。<br/><br/><br/>本文です。本文です。本文です。本文です。本文です。本文です。<br/>`,
  },
  {
    id: 3,
    title: 'APIで取得した記事タイトル３',
    thumbnailUrl: 'https://placehold.jp/800x400.png',
    createdAt: '2023-09-09T09:00:00.000Z',
    categories: ['JavaScript'],
    content: `
    本文です。本文です。本文です。本文です。本文です。本文です。<br/>本文です。本文です。本文です。本文です。本文です。<br/><br/>本文です。本文です。本文です。本文です。本文です。本文です。本文です。本文です。本文です。<br/><br/><br/>本文です。本文です。本文です。本文です。本文です。本文です。<br/>`,
  },
]
```

## React
Reactとは、JavaScriptのライブラリーの1つで、ユーザーインターフェイス(UI)を効率よく構築するために使います。

## App.js (記事一覧ページ)
```javascript
App.js
    
    import React from 'react'
    import './App.css'
    
    
    const PostsList = ({ src }) => {
    
      const formatDate = (dateString) => {
        const date = new Date(dateString);
    
        const options = { year: 'numeric', month: 'numeric', day: 'numeric' };
    return date.toLocaleDateString('ja-JP', options);
  }

  return (
    <div className="App">
      <header className="header-App">
        <a className="link" href='/'>Blog</a>
        <a className="link" href='/'>お問い合わせ</a>
      </header>

      {
        src.map((elem, index) => (
          <div key={index} className="posts-info">
            <ul >
              <li>
                <a href='/'>
                  <div className="date">{formatDate(elem.createdAt)}</div>
                  <div className="programming-language">{elem.categories.map((category, idx) => (
                    <span key={idx} className="category-box">{category}</span>
                  ))}</div>
                  <div className="title">{elem.title}</div>
                  <div className="content" dangerouslySetInnerHTML={{ __html: elem.content }}>
                  </div>
                </a>
              </li>
            </ul>
          </div>
        ))}
    </div>
    )}
    export default PostsList;
```


## インポート文
``` javascript
import React from 'react';
import './App.css';
```
インポートとは、データを外部から取り組んで現在の環境に取り入れること。
Reactを使用するにはインポートする必要があるため、
`import React from 'react';`と記述します。
`import './App.css';`は、スタイルシート（CSSファイル）をインポートしている。

##  コンポーネントの定義
```javascript
const PostsList = ({ src }) => {
```
コンポーネントとは、Reactで画面に表示されるUI部品のことです。

まずは、`PostsList`という名前で関数コンポーネントを定義。
`src`という名前のプロパティを受け取るようにしています。`src`は、投稿データの配列です
プロパティは、Reactコンポーネント間での情報共有の役割をしています。

## 内部関数の定義
```javascript
const formatDate = (dateString) => {
  const date = new Date(dateString);
  const options = { year: 'numeric', month: 'numeric', day: 'numeric' };
  return date.toLocaleDateString('ja-JP', options);
}
```
・`const formatDate = (dateString) => {`
`formatDate`の名前で関数を定義。
日付文字列をフォーマットで表示するためのもの。

`dateString`は、文字列形式で渡される。

・`const date = new Date(dateString);`
`dateString`をJavaScriptの"Date"オグジェクトに変換。

・`const options = { year: 'numeric', month: 'numeric', day: 'numeric' };`
日付を表示するためのオプションを定義。
年、月、日を数値形式で表示します。

・`return date.toLocaleDateString('ja-JP', options);`
`Date`オブジェクトを日本語のローカル日付文字列に変換して返す。

## コンポーネントのレンダリング
```javascript
return (
  <div className="App">
    {src.map((elem, index) => (
      <div key={index} className="posts-info">
        <ul>
          <li>
            <a href='/'>
              <div className="date">{formatDate(elem.createdAt)}</div>
              <div className="programming-language">
                {elem.categories.map((category, idx) => (
                  <span key={idx} className="category-box">{category}</span>
                ))}
              </div>
              <div className="title">{elem.title}</div>
              <div className="content" dangerouslySetInnerHTML={{ __html: elem.content }}></div>
            </a>
          </li>
        </ul>
      </div>
    ))}
  </div>
);
```
・`<div className="App">`
`div`要素でコンポーネント全体を囲む。
`className`をつけることで、スタイルシートでこのクラスに対するスタイル設定ができる。

・`{src.map((elem, index) => (`
`src`配列を`map`メソッドでループし、各要素を`elem`として処理する。
`index`は現在の要素のインデックスです。

・`<div key={index} className="posts-info">`
各投稿を囲む`div`要素。
`key`属性には`index`を設定する。

・`<ul>`と`<li>`
投稿をリスト形式で表示するためのHTML要素。

・`<a href='/'>:`
投稿全体をリンクで表示。`href`属性はリンク先のURLを指定する。

・`<div className="date">{formatDate(elem.createdAt)}</div>`
`formatDate`関数を使って、日付をフォーマットさせる。

・`<div className="programming-language">:`
投稿のカテゴリ（プログラミング言語）を表示します。
`elem.categories`配列をループして各カテゴリを表示します。

・`<div className="title">{elem.title}</div>`
投稿のタイトルを表示

・`<div className="content" dangerouslySetInnerHTML={{ __html: elem.content }}></div>`
`dangerouslySetInnerHTML`を使って、HTML文字列をそのままレンダリングしています。

・`export default PostsList;`

`export`と宣言するとこで、他のファイルでも再利用できる仕組みです。

## index.js (アプリを起動するエントリーポイント)

```javascript
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { posts } from './data/posts';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App src={posts}/>

  </React.StrictMode>
);
```
`1.インポート文`
・`import ReactDOM from 'react-dom/client';`
`ReactDOM`は、Reactコンポーネントを実際のDOMにレンダリングするためのライブラリです。

・`import App from './App';`
Appコンポーネントをインポート。
このコンポーネントがアプリケーションのメインコンポーネントとなります。

・`import { posts } from './data/posts';`
posts.jsにある、`posts`データをインポートしています。
このデータは、`App`コンポーネントに渡されるプロパティ（`props`）として使用。

:::note warn
posts.jsについては、コード項目を参照してください！
:::



`ルートの作成とレンダリング`
・`const root = ReactDOM.createRoot(document.getElementById('root'));`
`createRoot`メソッドを使って、Reactのアプリケーションルートを作成。
`document.getElementById('root')`は、HTMLファイル内の`id`が`root`である要素を取得します。
この要素がReactアプリケーションのマウントポイントとなります。

`3.React.StrictMode`
・`<React.StrictMode>`
`React.StrictMode`は、開発モードでのみ動作するラッパーコンポーネント。
アプリケーションの潜在的な問題を検出するために使用されます。

・`<App src={posts}/>:`
`App`コンポーネントをレンダリング。
レンダリングとは、コンポーネントのデータを基にHTMLを生成し、それをブラウザに表示する。

`src`というプロパティに`posts`データを渡しています。このデータは、`App`コンポーネント内で使用されます。

## ポイント
・関数コンポーネント
コンポーネント:UIの再利用可能な部品
関数として定義されるコンポーネント。

・JSX
JavaScript内で、HTMLのような構文を使うための拡張機能。
UIの構造を直感的に記述できます。

・Props（プロパティ）
コンポーネント間でデータを渡す役割。
親コンポーネントから子コンポーネントへデータを渡すことができる。

・レンダリング
コンポーネントのデータを基にHTMLを生成し、ブラウザに表示させる。

## まとめ
今回は、Reactを使用して投稿リストを表示するコンポーネントを作成してみました！
次回は、記事詳細ページの作成の記事を予定しています！
お楽しみに！