コンポーネントとは?
コンポーネントという言葉を聞いたことがありますか?これは、ウェブページを作るときの便利な「部品」のようなもので、ヘッダーやフッター、あるいはメインコンテンツなど、ページのさまざまな部分を簡単に再利用できます。
このコンポーネントの素晴らしいところは、部品の再利用によりコードをすっきりさせることと、それにより修正やテストが楽になることです。コンポーネントを上手に設計するコツは2つあります。1つは再利用性を意識することで、もう1つは外部から簡単に情報を渡せるようにしておくことです。
このコンポーネントの素晴らしいところは、部品の再利用によりコードをすっきりさせることと、それにより修正やテストが楽になることです。
つまり、「使い回しが効く」設計を心がけると、アプリケーション全体がグッと使いやすくなります。
今回作るパーツの概要
まずは、コンポーネントの概念を理解するために、見た目だけのコンポーネントを作ってみましょう!
- Header(ヘッダーコンポーネント)
- ChatMessage(メッセージ表示コンポーネント)
- ChatForm(ユーザー入力コンポーネント)
ヘッダーコンポーネント作成方法
まずは、チャットページのヘッダーコンポーネントを作ります。
export default function Header() {
return (
<header>
<h1
style={{
background: "#006BD6",
fontSize: "28px",
color: "white",
padding: "8px 10px",
boxShadow: "0 2px 4px rgba(0, 0, 0, 0.2)",
}}
>
チャットルーム
</h1>
</header>
);
}
Header
がコンポーネント名です。ヘッダーコンポーネントをlayout.tsxにインポートして、app/配下のページにヘッダーを適用させます。
import "./globals.css";
import { ReactNode } from "react";
import Header from "@/components/layout/Header"; // 追加
export default function Layout({ children }: { children: ReactNode }) {
return (
<>
<html lang="ja">
<body>
<Header /> // 追加
<main style={{ background: "#F1F3F7", width: "100%", height: "100vh" }} >{children}</main>
</body>
</html>
</>
);
}
ユーザー入力コンポーネントの作成方法
次に、チャットページのユーザー入力コンポーネントを作ります。
export default function ChatForm() {
return (
<div
style={{
position: "fixed",
bottom: 0,
width: "100%",
padding: 20,
background: "#fff",
}}
>
<div style={{ display: "flex", gap: 10 }}>
<input
type="text"
placeholder="メッセージを入力..."
style={{
width: "100%",
padding: 10,
borderRadius: 10,
border: "1px solid #ccc",
}}
/>
<button
style={{
padding: 10,
background: "#006BD6",
color: "white",
borderRadius: 10,
border: "none",
}}
>
送信
</button>
</div>
</div>
);
}
メッセージ表示コンポーネントの作成方法
画像を使う際にはnext/image
コンポーネントをインポートして最適化できます。
ここでは、Doodle Ipsumというサイトランダムな画像をアイコンとして取得しています。
import Image from "next/image";
export default function ChatMessage() {
return (
<div style={{ padding: "30px 20px", height: "100%" }}>
{/* 相手側のメッセージ */}
<div style={{ display: "flex", gap: 10 }}>
{/* サイトのURLでダミー画像を持ってくる */}
<Image
src="https://doodleipsum.com/700/avatar-2?i=0639d368201785f32891763286f61ca0"
alt=""
width={50}
height={50}
/>
<div
style={{
padding: "10px 20px",
marginTop: 5,
background: "#fff",
borderRadius: 10,
lineHeight: 1.5,
height: "fit-content",
}}
>
こんにちは!
</div>
</div>
{/* 自分のメッセージ */}
<div
style={{
display: "flex",
gap: 10,
justifyContent: "flex-end",
marginTop: 20,
}}
>
<div
style={{
padding: "10px 20px",
marginTop: 5,
background: "#006BD6",
borderRadius: 10,
lineHeight: 1.5,
height: "fit-content",
color: "white",
}}
>
こんにちは!
</div>
</div>
</div>
);
}
外部URLを使った画像の最適化
ただ、このままでは以下のようなエラーになります。
Server Error
Error: Invalid src prop (https://placeimg.com/140/140/any) on `next/image`, hostname "placeimg.com" is not configured under images in your `next.config.js`
See more info: https://nextjs.org/docs/messages/next-image-unconfigured-host
Image
コンポーネントで外部の画像を使うには、使用する外部ドメインをnext.config.js に設定しておく必要があります。
ここで使用したい画像パスは、「https://doodleipsum.com/700/avatar-2?i=0639d368201785f32891763286f61ca0」です。
そのため、protocol
には「https」、hostname
には「doodleipsum.com」を設定します。
/** @type {import('next').NextConfig} */
const nextConfig = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "doodleipsum.com",
},
],
},
};
export default nextConfig;
2つのコンポーネントの組み合わせ方法
ChatMessageコンポーネントとChatFormコンポーネントを組み合わせれば、アプリの骨組みは完成です!
import { ChatForm } from "@/components/chat/ChatForm";
import { ChatMessage } from "@/components/chat/ChatMessage";
export default function Home() {
return (
<>
<ChatMessage />
<ChatForm />
</>
);
}
参考サイト
宣伝:もしもよかったらご覧ください^^
『AIとコミュニケーションする技術(インプレス出版)』という書籍を出版しました🎉
これからの未来において「変わらない知識」を見極めて、生成AIの業界において、読まれ続ける「バイブル」となる本をまとめ上げました。
かなり自信のある一冊なため、もしもよろしければ、ご一読いただけますと幸いです^^