代码之家  ›  专栏  ›  技术社区  ›  Jace Johnson

我应该使用多个地图功能还是只使用一个

  •  0
  • Jace Johnson  · 技术社区  · 10 月前

    我目前正在使用NFL Api创建一个分析网站。我试图在我的反应组件中映射3个单独的数组。其中一个数组包含我从API检索到的玩家的名称 fetchFullNames 。另一个数组包含玩家头像的三分之一 fetchImages 然后一个数组保存每个玩家的id quarterbacks 。在我的return语句中,我试图映射这些数组中的每一个,显示5张牌,每个玩家一张,包含他们的名字和头像。我现在的代码是多次显示同一玩家的名字,也多次显示相同玩家的头像。我想知道我是否应该对return语句中的所有数据只使用一个map函数。

    这是我目前正在使用的代码:

    import { Link } from "react-router-dom";
    import _navbar from "../../NavBar/navbar";
    import React, { useEffect, useState } from "react";
    import styles from "./card.module.css";
    
    const quarterbacks = [3139477, 4241479, 3918298, 3915511, 2577417];
      const fetchFullName = async (id) => {
        const res = await fetch(
          `https://nfl-api-data.p.rapidapi.com/nfl-ath-fullinfo?id=${encodeURIComponent(id)}`,
          {
            headers: {
              "x-rapidapi-key": "secret key",
              "x-rapidapi-host": "nfl-api-data.p.rapidapi.com",
            },
          },
        );
        if (!res.ok) {
          throw new Error(`Name lookup for id '${id}' failed`);
        }
        return (await res.json()).athlete.fullName;
    
      };
      
      // returns an array of {id, name} objects
      const fetchFullNames = async (ids) =>
        Promise.all(ids.map(async (id) => ({ id, name: await fetchFullName(id) })));
    
    
      const fetchImage = async (id) => {
        const res = await fetch(
          `https://nfl-api-data.p.rapidapi.com/nfl-ath-img?id=${encodeURIComponent(id)}`,
            {
              headers: {
                "x-rapidapi-key": "secret key",
                "x-rapidapi-host": "nfl-api-data.p.rapidapi.com",
              },
            },
          );
          if(!res.ok) {
            throw new Error(`Image lookup for id '${id}' failed`);
            
          }
          return (await res.json()).image.href;
        
      }
      // Returns an array of the href for each player 
      const fetchImages = (ids) => 
        Promise.all(ids.map(async (id) => ({image : await fetchImage(id)})));
      
    
      
      
    
      export default function _quarterbacksPage() {
        const [names, setNames] = useState([]);
        const [images, setImages] = useState([]);
      
        useEffect(() => {
          fetchFullNames(quarterbacks).then(setNames).catch(console.error);
          fetchImages(quarterbacks).then(setImages).catch(console.error);
        }, []);
      
        return (
          <>
            <_navbar />
            <div className={styles.cards}>
              {quarterbacks.map(() => (
                <div className={styles.card}>   
                  {images.map(({image}) => (             
                    <img src={image} key={image} alt="player picture"/>
                  ))}
                  {names.map(({id, name }) => (
                    <Link className={styles.cardText} key={id} to={`/quarterback/${id}`}>
                      {name}
                    </Link>
                  ))}
                </div>
              ))}
            </div>
              
          </>
        );
      }
    
    2 回复  |  直到 10 月前
        1
  •  1
  •   jsejcksn    10 月前

    您可以单独关注每个ID并保留代码 DRY :

    const RAPIDAPI_KEY = "secret key";
    
    async function fetchJsonData(endpoint, params) {
      const init = {
        headers: new Headers([
          ["x-rapidapi-key", RAPIDAPI_KEY],
          ["x-rapidapi-host", "nfl-api-data.p.rapidapi.com"],
        ]),
      };
    
      const url = new URL("https://nfl-api-data.p.rapidapi.com");
      url.pathname = endpoint;
      if (params) url.search = new URLSearchParams(params).toString();
    
      const response = await fetch(url, init);
    
      if (!response.ok) {
        throw new Error(`Response not OK (${response.status})`, {
          cause: response,
        });
      }
    
      return response.json();
    }
    
    async function fetchFullName(id) {
      try {
        const data = await fetchJsonData("/nfl-ath-fullinfo", { id });
        return data.athlete.fullName;
      } catch {
        throw new Error(`Name lookup for id '${id}' failed`);
      }
    }
    
    async function fetchImage(id) {
      try {
        const data = await fetchJsonData("/nfl-ath-img", { id });
        return data.image.href;
      } catch {
        throw new Error(`Image lookup for id '${id}' failed`);
      }
    }
    
    async function fetchQuarterbackData(id) {
      const [name, imageUrl] = await Promise.all([
        fetchFullName(id),
        fetchImage(id),
      ]);
      return { id, name, imageUrl };
    }
    

    然后在组件中,您只需要映射一次:

    export default function _quarterbacksPage() {
      const [quarterbacks, setQuarterbacks] = useState([]);
    
      useEffect(() => {
        (async () => {
          try {
            const quarterbackIds = [3139477, 4241479, 3918298, 3915511, 2577417];
            const qbs = await Promise.all(quarterbackIds.map(fetchQuarterbackData));
            setQuarterbacks(qbs);
          } catch (cause) {
            console.error(cause);
          }
        })();
      }, []);
    
      return (
        <>
          <_navbar />
          <div className={styles.cards}>
            {quarterbacks.map(({ id, name, imageUrl }) => (
              <div key={id} className={styles.card}>
                <img src={imageUrl} alt="player picture" />
                <Link className={styles.cardText} to={`/quarterback/${id}`}>
                  {name}
                </Link>
              </div>
            ))}
          </div>
        </>
      );
    }
    
        2
  •  1
  •   James    10 月前

    将所有qb数据存储在一个状态变量中(作为对象数组)可能更容易。然后,您可以在映射qbData时适当地显示每个字段。

    const [qbData, setQbData] = useState([]);
    
    useEffect(() => {
      Promise.all([
        fetchFullNames(quarterbacks),
        fetchImages(quarterbacks)
      ])
      .then(([names, images]) => setQbData(
        quarterbacks.map((id, i) => ({ 
          id,
          name: names[i], 
          image: images[i]
        }))
      ))
    }, []);
    
    
    
    <div className={styles.cards}>
          {qbData.map(({id, name, image})) => (
            <div className={styles.card}>              
                <img src={image} key={image} alt="player picture"/>
                <Link className={styles.cardText} key={id} to={`/quarterback/${id}`}>
                  {name}
                </Link>
            </div>
          ))}
        </div>