メモ > 技術 > フレームワーク: React.js > React Router
React Router
2022年中にreact-router-domの理解を深めたい #React - Qiita
https://qiita.com/TMDM/items/0939ff52ab5b459303d7
React Router でルーティングを管理しよう(初心者向け) | Muscle Coding
https://musclecoding.com/react-router/
React Routerのルーティング実装
https://zenn.dev/takaya39/articles/4669c3fd1c7f04
■準備
今回は「プロジェクトを作成して開発」で作成したプロジェクトを使用する。
>cd C:\path\to\react_app
>npm install react-router-dom
>npm start
src/App.js の内容を以下のようにし、ページにアクセスして「react-router」と表示されることを確認する。
function App() {
return (
<div>
<h1>react-router</h1>
</div>
);
}
export default App;
■ルーティングの確認
以下のファイルを作成する。
src/routes/Home.js
import { Link } from "react-router-dom";
export const Home = () =>{
return (
<div>
<p>Home</p>
<ul>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
</div>
)
}
src/routes/About.js
import { Link } from "react-router-dom";
export const About = () =>{
return (
<div>
<p>About</p>
<ul>
<li><Link to="/">Home</Link></li>
</ul>
</div>
)
}
src/routes/Contact.js
import { Link } from "react-router-dom";
export const Contact = () =>{
return (
<div>
<p>Contact</p>
<ul>
<li><Link to="/">Home</Link></li>
</ul>
</div>
)
}
src/routes/Notfound.js
import { Link } from "react-router-dom";
export const Notfound = () =>{
return (
<div>
<p>Notfound</p>
<ul>
<li><Link to="/">Home</Link></li>
</ul>
</div>
)
}
以下のファイルを編集する。
src/App.js
import { Routes, Route } from "react-router-dom";
import { Home } from "./routes/Home";
import { About } from "./routes/About";
import { Contact } from "./routes/Contact";
import { Notfound } from "./routes/Notfound";
function App () {
return (
<div>
<h1>react-router</h1>
<Routes>
<Route path="/" element={ <Home /> } />
<Route path="/about" element={ <About /> } />
<Route path="/contact" element={ <Contact /> } />
<Route path="*" element={ <Notfound /> } />
</Routes>
</div>
);
}
export default App;
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
これで http://localhost:3000/ にアクセスすると、Homeの画面が表示される。
各リンクからAboutやContactに遷移でき、URLも変化する。
存在しないURLにアクセスされた場合、Notfoundの画面が表示される。
■データの取得
以下が参考になるか。
React Router v6のルーティング方法を解説 - createBrowserRouterとData APIsの活用法 | DevelopersIO
https://dev.classmethod.jp/articles/react-router-v6-4-createbrowserrouter-data-apis/
以下は参考記事のメモ。
Laravel x Inertia.js 現代のモノリス によるお手軽 SPA 開発 - Speaker Deck
https://speakerdeck.com/tutida/laravel-x-inertia-dot-js-xian-dai-nomonorisu-niyoruoshou-qing-spa-kai...
以下はChatGPTによるコード。
src/routes/Home.js
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
export const Home = () => {
const [posts, setPosts] = useState([]);
const [error, setError] = useState(null);
// 外部データを取得するための useEffect フック
useEffect(() => {
const fetchPosts = async () => {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=5");
if (!response.ok) {
throw new Error(`Error: ${response.statusText}`);
}
const data = await response.json();
setPosts(data);
} catch (err) {
setError(err.message);
}
};
fetchPosts();
}, []); // 空の依存配列により、コンポーネントがマウントされたときのみ実行
return (
<div>
<p>Home</p>
<ul>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
<h2>Posts</h2>
{error ? (
<p style={{ color: "red" }}>Failed to fetch posts: {error}</p>
) : posts.length > 0 ? (
<ul>
{posts.map((post) => (
<li key={post.id}>
{post.id}: {post.title}
</li>
))}
</ul>
) : (
<p>Loading...</p>
)}
</div>
);
};
■データの投稿
以下はChatGPTによるコード。
import { Link, useNavigate } from "react-router-dom";
import { useState } from "react";
export const Home = () => {
const [title, setTitle] = useState("");
const [body, setBody] = useState("");
//const navigate = useNavigate(); // 投稿後にリダイレクトさせる場合
const handleSubmit = async (e) => {
e.preventDefault();
try {
// POSTリクエストを送信
const response = await fetch("http://localhost/~test/react/post/post.php", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({ title, body }).toString(),
});
if (response.ok) {
console.log("データが正常に送信されました");
} else {
console.error("データ送信に失敗しました", response.statusText);
}
} catch (error) {
console.error("エラーが発生しました", error);
}
console.log("Title:", title);
console.log("Body:", body);
//navigate("/complete"); // 投稿後にリダイレクトさせる場合
};
return (
<div>
<p>Home</p>
<ul>
<li><Link to="/about">About</Link></li>
<li><Link to="/contact">Contact</Link></li>
</ul>
<form onSubmit={handleSubmit}>
<dl className="mb-2">
<dt>タイトル</dt>
<dd><input type="text" name="title" value={title} onChange={(e) => setTitle(e.target.value)} className="border-2 p-1 block w-64" /></dd>
<dt>本文</dt>
<dd><textarea name="body" value={body} onChange={(e) => setBody(e.target.value)} className="border-2 p-1 block w-64 h-28" /></dd>
</dl>
<p>
<button type="submit" className="border-2 p-2">作成</button>
</p>
</form>
</div>
);
};
post.php の内容は以下のとおり。
同じ階層に post.log があり、そこに投稿データが記録される。
<?php
header('Access-Control-Allow-Origin: http://localhost:3000'); // フロントエンドのオリジンを許可
header('Access-Control-Allow-Methods: POST'); // 許可するHTTPメソッド
header('Access-Control-Allow-Headers: Content-Type'); // 許可するヘッダー
$title = $_POST['title'];
$body = $_POST['body'];
if (file_put_contents('post.log', "title=" . $title . "\nbody=" . $body . "\n") === false) {
exit('NG');
}
echo 'OK';
「Access-Control-Allow-Origin」などについては以下を参照
なんとなく CORS がわかる...はもう終わりにする。 #JavaScript - Qiita
https://qiita.com/att55/items/2154a8aad8bf1409db2b