How to fetch data from multiple urls at once?

DGB :

I have a function that fetches from a url in React

const DataContextProvider = (props) => {
  const [isLoading, setLoading] = useState(false);
  const [cocktails, setCocktails] = useState([]);

  useEffect(() => {
    const fetchCocktailList = async () => {
      const baseUrl = 'https://www.thecocktaildb.com/api/json/v1/1/';
      setLoading(true);
      try {
        const res = await fetch(`${baseUrl}search.php?s=margarita`);
        const data = await res.json();
        console.log(data);
        setCocktails(data.drinks);
        setLoading(false);
      } catch (err) {
        console.log('Error fetching data');

        setLoading(false);
      }
    };

    fetchCocktailList();
  }, []);


How I'm mapping data so far.

const DrinkList = () => {
  const { cocktails } = useContext(DataContext);
  return (
    <div className='drink-list-wrapper'>
      {cocktails.length > 0 &&
        cocktails.map((drink) => {
          return <DrinkItem drink={drink} key={drink.idDrink} />;
        })}
    </div>
  );
};

However I want to fetch from this url also ${baseUrl}search.php?s=martini

I would like a good clean way to do this and set my state to both of the returned data.

jsejcksn :

Here's a method which will let you specify the cocktail names as dependencies to the useEffect so you can store them in your state and fetch new drink lists if you want new recipes. If not, it'll just be a static state variable.

  • I've also added another state variable errorMessage which you use to pass an error message in the case of failure.
  • Also, you should include the appropriate dependencies in your useEffect hook. The setState functions returned by calls to useState are stable and won't trigger a re-run of the effect, and the cocktailNames variable won't trigger a re-run unless you update it with new things to fetch.
const DataContextProvider = (props) => {
  const [isLoading, setLoading] = useState(false);
  const [cocktails, setCocktails] = useState([]);
  const [errorMessage, setErrorMessage] = useState(''); // holds an error message in case the network request dosn't succeed
  const [cocktailNames, setCocktailNames] = useState(['margarita', 'martini']); // the search queries for the `s` parameter at your API endpoint

  useEffect(() => {
    const fetchCocktailLists = async (...cocktailNames) => {
      const fetchCocktailList = async (cocktailName) => {
        const baseUrl = 'https://www.thecocktaildb.com/api/json/v1/1/search.php';
        const url = new URL(baseUrl);
        const params = new URLSearchParams({s: cocktailName});
        url.search = params.toString(); // -> '?s=cocktailName'
        const res = await fetch(url.href); // -> 'https://www.thecocktaildb.com/api/json/v1/1/search.php?s=cocktailName'
        const data = await res.json();
        const {drinks: drinkList} = data; // destructured form of: const drinkList = data.drinks;
        return drinkList;
      };

      setLoading(true);
      try {
        const promises = [];
        for (const cocktailName of cocktailNames) {
          promises.push(fetchCocktailList(cocktailName));
        }
        const drinkLists = await Promise.all(promises); // -> [[drink1, drink2], [drink3, drink4]]
        const allDrinks = drinkLists.flat(1); // -> [drink1, drink2, drink3, drink4]
        setCocktails(allDrinks);
      }
      catch (err) {
        setErrorMessage(err.message /* or whatever custom message you want */);
      }
      setLoading(false);
    };

    fetchCocktailList(...cocktailNames);
  }, [cocktailNames, setCocktails, setErrorMessage, setLoading]);
};

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=11781&siteId=1