reactjs 我检查了无数次,却找不出我的错误在哪里:未捕获的类型错误:无法读取未定义的属性(读取"lat')

jm81lzqq  于 2023-01-04  发布在  React
关注(0)|答案(3)|浏览(134)

我一直在尝试使用OpenWeatherMap API来学习编程,但在控制台中弹出了一系列TypeError问题。我的假设是,我的程序试图在完成获取之前使用API中的数据,但我设置了获取函数,直到收到响应才将它们添加到相应的状态。并尝试了许多解决方案。我在下面包含了我的App.js代码(提交了API密钥):

function App() {
  // initialize location as UWS (no actual reason)
  const [location, setLocation] = useState("10024");

  // GeoCoder API data to feed into the main weather API
  const [inputData, setInputData] = useState();

  // Main weather API data to feed to UI
  const [apiData, setApiData] = useState();

  // GeoCoder API used for fetching latitude & longitude
  const geoCoder = `http://api.openweathermap.org/geo/1.0/zip?zip=${location},US&appid=${API__KEY}`;

  // Main weather API used for feeding data to the UI (based on lat & lon from geoCoder API)
  const url = `https://api.openweathermap.org/data/2.5/weather?lat=${inputData.lat}&lon=${inputData.lon}&appid=${API__KEY}&units=imperial`;

  // Use user-submitted zip code to fetch latitude & longitude from geoCoder API
  const getInputData = async () => {
    const res = await fetch(geoCoder);
    const jsonRes = await res.json();
    setInputData(jsonRes);
  };

  // Use Zip code from geoCoder API to fetch data from main weather API
  const getApiData = async () => {
    const res = await fetch(url);
    const jsonRes = await res.json();
    setApiData(jsonRes);
  };

  // Initialize website with data
  useEffect(() => {
    getInputData();
  }, []);

  return (
    <div className="container">
      <Title />
      <Search
        location={location}
        setLocation={setLocation}
        getInputData={getInputData}
        getApiData={getApiData}
      />
      <Pinpoint apiData={apiData} />
      <ForecastPreview apiData={apiData} />
      <ForecastDetails apiData={apiData} />
    </div>
  );
}

其他背景:apiData状态作为 prop 传递给子组件,并用于根据存储在apiData中的数据在屏幕上呈现数据。
控制台中有多个错误,就像我在问题标题中包含的错误一样,可能都源于同一个问题。
在过去的三个小时里一直想不通。任何帮助都是非常感谢的。

ahy6op9u

ahy6op9u1#

请尝试以下步骤来获取正确的URL:
1.使用正确的数据模型为inputData提供初始值
1.当inputData未就绪时,为url指定回退值
下面的示例将使用公共API,因此不需要密钥,如果切换到项目API,它也应该可以工作。
示例:(codesandbox上的简化现场演示)
inputData需要正确的数据模型,以便url读取其属性:

// GeoCoder API data to feed into the main weather API
const [inputData, setInputData] = useState({ lat: null, lon: null });

inputData正在获取但尚未就绪时,url需要回退值(此处使用null,但它可以是任何值,具体取决于如何使用它):

// Main weather API used for feeding data to the UI (based on lat & lon from geoCoder API)
const url =
  inputData?.lat && inputData?.lon
    ? `https://api.openweathermap.org/data/2.5/weather?lat=${inputData.lat}&lon=${inputData.lon}&appid=API__KEY&units=imperial`
    : null;

可选:可以在useEffect内部创建数据获取函数,因此不需要将其添加到依赖项数组中。

// Initialize website with data
useEffect(() => {
  const initInputData = async () => {
    if (!geoCoder) return;
    const res = await fetch(geoCoder);
    if (!res.ok) throw new Error("fetch failed");
    const jsonRes = await res.json();
    setInputData(jsonRes);
  };
  initInputData().catch((error) => console.error(error));
}, [geoCoder]);

可能还有其他问题需要解决,但希望这至少可以帮助生成正确的网址没有错误。

wnrlj8wa

wnrlj8wa2#

始终为状态变量设置initial value

const [inputData, setInputData] = useState({ lat: null, lon: null });
const [apiData, setApiData] = useState({})
xvw2m8pv

xvw2m8pv3#

更新:这里的解决方案非常简单,我觉得自己像个白痴,没有更早地注意到它。评论是正确的,因为我需要一个后备。我设置了利用获取的数据的组件,当所需的状态属性是真实的时,这些组件将被有条件地呈现。为了简单起见,我在核心文档中更改了一些内容,但解决方案工作的原因仍然适用于这两种情况。如果apiData。main和forecastData.list(这是在发布初始问题后创建的)都是truthy,呈现组件带有获取的项,否则呈现一个空字符串。

{apiData.main && forecastData.list ? (
    <>
      <Pinpoint apiData={apiData} />
      <ForecastPreview apiData={apiData} />
      <ForecastDetails
        apiData={apiData}
        forecastData={forecastData}
        getForecastData={getForecastData}
      />
    </>
  ) : (
    ""
  )}

相关问题