npx create-remix@latest
名前は?
? Where would you like to create your app? remix-blog
テンプレートのタイプは?
? What type of app do you want to create?
❯ Just the basics
どこにデプロイする?
? Where do you want to deploy? Choose Remix if you're unsure, it's easy to change deployme
nt targets.
❯ Cloudflare Workers
TypeScriptかJavaScript?
? TypeScript or JavaScript?
❯ JavaScript
? Do you want me to run `npm install`? Y
これでcloudflareに簡単に上げることができるテンプレートが出来上がる
appフォルダにstylesフォルダを作り、global.cssファイルを作る
それをroot.jsxにインポートすることでcssが反映されるようになる
import {
Links,
LiveReload,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "remix";
import globalStylesUrl from "~/styles/global.css";
export function meta() {
return {
charset: "utf-8",
title: "New Remix App",
viewport: "width=device-width,initial-scale=1",
};
}
export function links() {
return [
{ rel: "stylesheet", href: globalStylesUrl},
];
}
export default function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}
appフォルダにnavbar.jsxを作り
root.jsxにインポートし
bodyの中に含める
import { Link, } from "remix";
export default function Navbar() {
return (
<header className="remix-app__header">
<div className="container remix-app__header-content">
<Link to="/" title="Remix" className="remix-app__header-home-link">
<RemixLogo />
</Link>
<nav aria-label="Main navigation" className="remix-app__header-nav">
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/blog">Blog</Link>
</li>
</ul>
</nav>
</div>
</header>
);
}
function RemixLogo(props) {
return (
<svg
viewBox="0 0 659 165"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
aria-labelledby="remix-run-logo-title"
role="img"
width="106"
height="30"
fill="currentColor"
{...props}
>
<title id="remix-run-logo-title">Remix Logo</title>
<path d="M0 161V136H45.5416C53.1486 136 54.8003 141.638 54.8003 145V161H0Z M133.85 124.16C135.3 142.762 135.3 151.482 135.3 161H92.2283C92.2283 158.927 92.2653 157.03 92.3028 155.107C92.4195 149.128 92.5411 142.894 91.5717 130.304C90.2905 111.872 82.3473 107.776 67.7419 107.776H54.8021H0V74.24H69.7918C88.2407 74.24 97.4651 68.632 97.4651 53.784C97.4651 40.728 88.2407 32.816 69.7918 32.816H0V0H77.4788C119.245 0 140 19.712 140 51.2C140 74.752 125.395 90.112 105.665 92.672C122.32 96 132.057 105.472 133.85 124.16Z" />
<path d="M654.54 47.1035H611.788L592.332 74.2395L573.388 47.1035H527.564L568.78 103.168L523.98 161.28H566.732L589.516 130.304L612.3 161.28H658.124L613.068 101.376L654.54 47.1035Z" />
</svg>
);
}
...
export default function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Navbar />
<div className="remix-app__main" style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.4" }}>
<div className="container remix-app__main-content">
<Outlet />
</div>
</div>
<ScrollRestoration />
<Scripts />
<LiveReload />
</body>
</html>
);
}
root.jsxのApp()の中にOutletコンポーネントが含まれている
この中がapp/routes以下のファイルに相当するようになる
<Link to={`/blog/posts/${post.id}`}>{post.title}</Link>
このリンク先がapp/routes/blog/posts/$PostId.jsx
ファイルを表示
loader関数の中のparams.PostIdで今のslugを取得している
import {Link, useLoaderData} from 'remix'
import blogStyles from "~/styles/blog.css";
export function links() {
return [{ rel: "stylesheet", href: blogStyles }];
}
export let loader= ({params}) => {
const post = [
{
id: 1,
title: "First post on Remix ",
content:"Remix is a great framework...."
},
{
id: 2,
title: "Another post about Remix",
content: "It has very good features...."
},
{
id: 3,
title: "Yet another post about remix",
content: "It has very good features plus more...."
}
].find((p)=> p.id === Number(params.PostId))
if (!post) throw Error("No posts found")
const data = {...post}
return data
}
export default function GetPost() {
const post= useLoaderData()
return (
<>
<h2>{post.title}</h2>
<p>{post.content}</p>
</>
)
}
データベースなどと連携している場合
loader関数内でデータを取得する
export let loader= ({params}) => {
let res = fetch("https://api...")
return res.json()
}
のようにすることができる
参考