Skip to content

Instantly share code, notes, and snippets.

@aidiary
Last active November 25, 2021 11:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aidiary/8342f8c7e575b55ff53a727e2cc48926 to your computer and use it in GitHub Desktop.
Save aidiary/8342f8c7e575b55ff53a727e2cc48926 to your computer and use it in GitHub Desktop.
[React] サーバからasync/awaitでデータをfetchする例
import React, { useCallback, useEffect, useState } from 'react';
import './App.css';
import MoviesList from './components/MoviesList';
function App() {
const [movies, setMovies] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const fetchMovieHandler = useCallback(async () => {
setIsLoading(true);
setError(null);
// promiseでthenを連続する代わりにawaitを使って書ける
try {
const response = await fetch('https://swapi.dev/api/films/');
if (!response.ok) {
throw new Error('Something went wrong!');
}
const data = await response.json();
const transformedMovies = data.results.map((movieData) => {
return {
id: movieData.episode_id,
title: movieData.title,
openingText: movieData.opening_crawl,
releaseDate: movieData.release_date,
};
});
setMovies(transformedMovies);
} catch (error) {
setError(error.message);
}
setIsLoading(false);
}, []);
useEffect(() => {
fetchMovieHandler();
}, [fetchMovieHandler]);
let content = <p>Found no movies.</p>;
if (movies.length > 0) {
content = <MoviesList movies={movies} />;
}
if (error) {
content = <p>{error}</p>;
}
if (isLoading) {
content = <p>Loading...</p>;
}
return (
<React.Fragment>
<section>
<button onClick={fetchMovieHandler}>Fetch Movies</button>
</section>
<section>{content}</section>
</React.Fragment>
);
}
export default App;
import { useEffect, useState } from 'react';
import Card from '../UI/Card';
import classes from './AvailableMeals.module.css';
import MealItem from './MealItem/MealItem';
const AvailableMeals = () => {
const [meals, setMeals] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [httpError, setHttpError] = useState();
useEffect(() => {
const fetchMeals = async () => {
const response = await fetch(
'https://react-http-91412-default-rtdb.firebaseio.com/meals'
);
if (response.ok) {
throw new Error('Something went wrong!');
}
const responseData = await response.json();
const loadedMeals = [];
for (const key in responseData) {
loadedMeals.push({
id: key,
name: responseData[key].name,
description: responseData[key].description,
price: responseData[key].price,
});
}
setMeals(loadedMeals);
setIsLoading(false);
};
fetchMeals().catch((error) => {
setIsLoading(false);
setHttpError(error.message);
});
}, []);
if (isLoading) {
return (
<section className={classes.MealsLoading}>
<p>Loading...</p>
</section>
);
}
if (httpError) {
return (
<section className={classes.MealsError}>
<p>{httpError}</p>
</section>
);
}
const mealsList = meals.map((meal) => (
<MealItem
key={meal.id}
id={meal.id}
name={meal.name}
description={meal.description}
price={meal.price}
/>
));
return (
<section className={classes.meals}>
<Card>
<ul>{mealsList}</ul>
</Card>
</section>
);
};
export default AvailableMeals;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment