環境の準備
①ターミナルで、アプリケーションを作成する。
$ npx create-next-app@latest
$ cd <プロジェクト名>
$ yarn dev
② 必要なパッケージをインストールする。
公式サイト:Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
③ 不要なファイルを削除する。
api
styles/home.module.css
コンポーネント・ファイル構成
├── components
| └── Layout.js
├── pages
| ├── pokemon
| | └── [id].js
| ├── _app.js
| └── index.js
├── package-lock.json
├── package.json
├── postcss.config.js
└── twilwind.config.js
公式サイト:PokeAPI
components/Layout.js
import Head from 'next/head';
const Layout = ({ title, children }) => {
return (
<div className='bg-gray-100'>
<Head>
<title>{title}</title>
<link rel='icon' href='/favicon.ico' />
</Head>
<main className='container mx-auto max-w-3xl pt-8 min-h-screen'>
{children}
</main>
</div>
);
};
export default Layout;
pages/pokemon/[id].js
import Layout from '../../components/Layout';
import Link from 'next/link';
const Pokemon = ({ pokemon }) => {
const zeroPadding = (num, len) => {
// 指定した数値の前に指定した桁数分0を追加したあと、後ろから0桁を返す
return (Array(len).join('0') + num).slice(-len);
};
return (
<Layout title={pokemon.name}>
<div className='m-auto w-2/3'>
<div className='flex flex-col bg-white rounded-md p-8 aspect-square justify-center shadow-lg'>
<span className='ml-2 font-light'>
No.{zeroPadding(pokemon.id + 1, 3)}
</span>
<img className='mx-auto' src={pokemon.image} alt={pokemon.name} />
<h2 className='text-2xl mt-6 mb-2 font-bold'>{pokemon.name}</h2>
{pokemon.types.map((type, index) => (
<p key={index}>{type.type.name}</p>
))}
</div>
</div>
<p className='mt-10 text-center'>
<Link href='/'>
<a>
<button className='focus:outline-none text-white text-sm py-2.5 px-5 rounded-md bg-blue-500 hover:bg-blue-700 hover:shadow-lg'>
一覧に戻る
</button>
</a>
</Link>
</p>
</Layout>
);
};
//getServerSidePropsを利用してデータを取得しページに表示させる
export const getServerSideProps = async (context) => {
const { id } = context.query;
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${id}`);
const pokemon = await res.json();
const paddedId = ('00' + id).slice(-3);
pokemon.image = `https://assets.pokemon.com/assets/cms2/img/pokedex/detail/${paddedId}.png`;
return {
props: { pokemon },
};
};
export default Pokemon;
pages/index.js
import Layout from '../components/Layout';
import Link from 'next/link';
export default function Home({ pokemon }) {
/**
* 足りない桁数を0埋めする関数
* @param num: 表示させたい数値
* @param len: 表示させたい桁数
* @returns {string}
*/
const zeroPadding = (num, len) => {
// 指定した数値の前に指定した桁数分0を追加したあと、後ろから0桁を返す
return (Array(len).join('0') + num).slice(-len);
};
return (
<Layout title='NextJS PokeDex'>
{/* //grid-cols-{n}ユーティリティを使用して、n個の同じサイズの列を持つグリッドを作成 */}
<div className={'grid grid-cols-3 gap-3'}>
{pokemon.map((item, index) => (
<p key={index}>
<Link href={`/pokemon/${index + 1}`}>
<a className='border-b-4 py-4 border-grey my-0 hover:shadow-md capitalize flex items-center text-xl font-bold bg-gray-100 shadow-lg'>
<span className='mr-2 font-light'>
{zeroPadding(index + 1, 3)}
</span>
<img
src={item.image}
alt={item.name}
className='w-10 h-10 mr-2 font-bold'
/>
{item.name}
</a>
</Link>
</p>
))}
</div>
</Layout>
);
}
//getServerSidePropsを利用してデータを取得しページに表示させる
export const getStaticProps = async () => {
const res = await fetch('https://pokeapi.co/api/v2/pokemon?limit=150');
const { results } = await res.json();
const pokemon = results.map((pokeman, index) => {
const paddedId = ('00' + (index + 1)).slice(-3);
const image = `https://assets.pokemon.com/assets/cms2/img/pokedex/detail/${paddedId}.png`;
return { ...pokeman, image };
});
return {
props: { pokemon },
};
};
styles/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
tailwind.config.js
module.exports = {
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
};
参考サイト
Build a Pokedex with NextJS and Tailwind CSS
Crea una pokedex con React, NextJS y Apollo GraphQL