今回は、NEXT.JSとSanity.ioを使って簡単な画像一覧アプリを作成します。完成は下記の通りです
キャラクター画像は、こちらのサイトから使っています。
初期画面
それぞれのカードをクリックすると、キャラクターの説明リンクに飛びます!
zoroをクリックすると、”localhost:3000/character/zoro"に遷移します。Homeボタンを押すと”localhost:3000/”に戻ります。
sanity.ioに新しい画像データを保存すると、ブラウザに表示されます。
下記の動画を参考に作成しました。まずこちらの動画を参考にされてください。
参考動画
NEXT.JSのSet up
npx create-next-app@latest frontend
Sanity.ioのSet up
sanity init
>Create new project: "yes"
>Your project name: "backend"
>Use the default dtaset configuration? "yes"
>Project output path: "Enter"
>Select project template: "Clean project with no predefined schemas"
モジュールをインストール
nextjsアプリケーションに下記のモジュールをインストールします。
npm install next-sanity @sanity/image-url
ここまでで必要な準備は整ったので、次はコードを書いていきます。
index.js
index.js
import { sanityClient, urlFor } from '../sanity'
import Link from 'next/link'
const Home = ({ characters }) => {
return (
<div>
{characters && (
<div>
<h1>Characters</h1>
<div
style={{ display: 'grid', gap: '1px', gridTemplateColumns: '2fr 2fr 2fr' }}
>
{characters.map((character) => (
<Link
className='card'
key={character._id}
href={`character/${character.slug.current}`}>
<div className='card'>
<img
src={urlFor(character.image)}
alt={character.name}
style={{ height: '70%', }}
/>
<h3>{character.name}</h3>
</div>
</Link>
))}
</div>
</div>
)}
</div>
)
}
export const getServerSideProps = async () => {
const query = '*[_type == "character"]'
const characters = await sanityClient.fetch(query);
if (!characters.length) {
return {
props: {
characters: []
},
}
} else {
return {
props: {
characters: characters,
}
}
}
}
export default Home;
[slug].js
[slug].js
import Link from "next/link";
import { sanityClient, urlFor } from "../../sanity";
const Character = ({ name, image }) => {
return (
<div>
<h1><b>{name}</b></h1>
<img
style={{ height: '300px' }}
src={urlFor(image)} alt={name}
/>
<br />
<Link href="/">
<button>Home</button>
</Link>
</div>
)
}
export const getServerSideProps = async (pageContext) => {
const pageSlug = pageContext.query.slug;
const query = `*[ _type == "character" && slug.current == $pageSlug][0]{
name,
image,
}`
const character = await sanityClient.fetch(query, {
pageSlug
})
if (!character) {
return {
props: null,
notFound: true,
}
} else {
return {
props: {
name: character.name,
image: character.image,
}
}
}
}
export default Character
sanity.js
このファイルが設定ファイルになります。
sanity.js
import { createClient } from 'next-sanity'
import createImageUrlBuilder from '@sanity/image-url'
const config = {
dataset: process.env.NEXT_PUBLIC_SANITY_DATASET || 'production',
projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID,
apiVersion: '2021-10-21',
useCdn: process.env.NODE_ENV === 'production',
}
export const sanityClient = createClient(config)
export const urlFor = (source) => createImageUrlBuilder(config).image(source)
globals.css
cardのスタイルだけ追加しました。
globals.css
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
body {
color: white;
background: black;
}
}
.card{
/* preview */
width: 200px;
height: 260px;
background-color: #fff;
margin: 5px auto;
padding: 5px;
/* border */
border: 2px solid #ccc;
/* border-radius */
border-radius: 15px;
/* box-shadow */
box-shadow: 0px 8px 16px -2px rgba(10,10,10,0.1), 0px 0px 0px 1px rgba(10,10,10,0.02);
}
.env
NEXT_PUBLIC_SANITY_DATASET="datasetを記述"
NEXT_PUBLIC_SANITY_PROJECT_ID="projectIdを記述"
schemas/character.js
character.js
export default {
name: 'character',
title: 'Character',
type: 'document',
fields: [
{
name: 'name',
title: 'Name',
type: 'string',
},
{
name: 'image',
title: 'Image',
type: 'image',
options: {
hotspot: true,
}
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'name',
maxLength: 100,
}
},
]
}
参考動画
さいごに
今度は、Airbnbクローンを自作してみたいですね!
参考動画では、Google maps Platformを使っています。こちらは、無料制限がありますのでご注意ください。