はじめに
前回記事の続きです。
Step1:API通信
Step2:ポケモンの一覧を取得する
Step3:CardListを作成する←いまここ。
成果物
ソースコード
src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ThemeProvider, createTheme } from '@mui/material';
// QueryClient インスタンスの作成
const queryClient = new QueryClient();
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
const theme = createTheme({
palette: {
primary: {
main: '#556cd6',
},
secondary: {
main: '#19857b',
},
},
});
root.render(
<React.StrictMode>
<ThemeProvider theme={theme}>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</ThemeProvider>
</React.StrictMode>
);
今回からmuiを利用。そのため、Providerの設定をしています。
src/App.tsx
import React from 'react';
import { Home } from './pages/Home';
function App() {
return <Home />;
}
export default App;
src/pages/Home.tsx
import { PokemonComponent } from '../components/PokemonComponent';
export const Home = () => {
return (
<div>
<h1>ポケモン表示</h1>
<PokemonComponent />
</div>
);
};
Pageとコンポーネントを分けたいため、Page表示用のコンポーネントを作成しています。
src/components/PokemonComponent.tsx
import React from 'react';
import { usePokemons } from '../api/pokemon/api';
import { isNullish } from '../common/common';
import { CardList } from './PokemonCardList';
export const PokemonComponent: React.FC = () => {
const { listQuery, detailsQueries } = usePokemons(20, 0);
if (isNullish(detailsQueries)) return <div>Loading...</div>;
console.log('listQuery', listQuery);
console.log('HIT8 detailsQueries', detailsQueries);
// 一覧データのローディング中
if (
listQuery.isLoading ||
isNullish(listQuery.data) ||
isNullish(detailsQueries)
) {
return <div>Loading pokemons...</div>;
}
// 一覧データ取得時のエラー
if (listQuery.isError) {
return <div>Error: {listQuery.error.message}</div>;
}
return (
<div>
<h2>Pokemon List</h2>
<CardList detailsQueries={detailsQueries} />
</div>
);
};
src/components/PokemonCardList.tsx
import React from 'react';
import { UseQueryResult } from '@tanstack/react-query';
import { Card } from './Card';
import { Pokemon } from '@bgoff1/pokeapi-types';
import { Grid } from '@mui/material';
interface CardListProps {
detailsQueries: UseQueryResult<Pokemon, Error>[];
}
export const CardList: React.FC<CardListProps> = ({ detailsQueries }) => {
return (
<Grid container spacing={2}>
{detailsQueries.map((query, index) => (
<Grid item xs={12} sm={6} md={4} key={index}>
{query.isLoading || !query.data ? (
<div>Loading...</div>
) : (
<Card
id={query.data.id}
name={query.data.name}
image={query.data.sprites.front_default ?? ''}
/>
)}
</Grid>
))}
</Grid>
);
};
src/components/Card.tsx
interface CardProps {
id: number;
name: string;
image: string;
}
export const Card: React.FC<CardProps> = ({ id, name, image }) => {
return (
<div className="card">
<div className="card-id">#{id}</div>
<div className="card-name">{name}</div>
<div className="card-image">
<img src={image} alt={name} />
</div>
</div>
);
};