You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React应用添加特定函数时出现Cannot set properties of null错误求助

问题

我在React应用里写了一段调用API的代码,输入国家名称返回对应首都。为了输出大小写规范的国名,额外加了个从API获取标准国名的函数。但只要保留这段获取国名的代码,绝大多数情况下会报错;删掉就完全正常。偶尔微调代码能暂时好,但刷新网页问题又回来。控制台明明能看到两个输出结果,还是报错。

代码如下:

function SearchButton() {
  async function GetCountryName(countryInput) { //Gets correctly capitalised country name
    const response = await fetch(`https://restcountries.com/v3.1/name/${countryInput}?fields=name`);
    const text = await response.text();
    let countryOutput = text.split('\",\"')[0]; //Removes superfluous characters after name
    countryOutput = countryOutput.split('\":\"')[1]; //Removes superfluous characters before name
    console.log(countryOutput);
    return countryOutput;
  }

  const displayResult = document.getElementById("output"); //Gets output location

  async function handleClick() { //Searches in API for the country in the textbox
    const countryInput = document.getElementById("Country").value.toLowerCase(); //Gets input
    if (countryInput){
      const response = await fetch(`https://restcountries.com/v3.1/name/${countryInput}?fields=capital`); //Finds capital
      const text = await response.text();
      
      const countryOutput = await GetCountryName(countryInput);

      if (!text.includes("capital")) { //If there is not a valid output for the input
        displayResult.innerHTML = `Please enter a country.`;
      } else {
        const textOut = text.split('\"]')[0]; //Removes superfluous characters after capital
        const textFinal = textOut.split('[\"')[1]; //Removes superfluous characters before capital
        console.log(countryOutput);
        console.log(textFinal);
        displayResult.innerHTML = `The capital of ${countryOutput} is ${textFinal}`;
      }
    } else { //If clicked without search term
      displayResult.innerHTML = `Please enter a country.`;
    }
  }

  return (
    <button type="button" id="SearchButton" onClick={handleClick}>
    Search
    </button>);
}
解决方案

问题根源

  1. 违反React数据驱动原则,直接操作DOM:组件初始化时就用document.getElementById获取DOM元素,但React组件会频繁重渲染,这个引用随时可能失效,后续修改innerHTML时必然报错。
  2. 字符串分割解析JSON极其脆弱:API返回的JSON格式稍有变化(比如字段顺序、多了空格),分割就会失败,拿到undefined,插入页面时触发错误。
  3. 无请求错误处理:网络超时、API返回错误码时,fetch不会主动抛错,后续处理错误文本时必然出问题。

修复后的代码

import { useState } from 'react';

function SearchButton() {
  // 用React状态管理结果,不再直接操作DOM
  const [result, setResult] = useState('');

  async function getCountryName(countryInput) {
    try {
      const response = await fetch(`https://restcountries.com/v3.1/name/${countryInput}?fields=name`);
      // 检查请求是否成功
      if (!response.ok) throw new Error('国名请求失败');
      // 直接解析JSON,不用字符串分割
      const data = await response.json();
      // 优先取官方名称,没有就取通用名称
      return data[0]?.name?.official || data[0]?.name?.common;
    } catch (err) {
      console.error('获取国名出错:', err);
      return null;
    }
  }

  async function handleClick() {
    const countryInput = document.getElementById("Country").value.trim().toLowerCase();
    if (!countryInput) {
      setResult('Please enter a country.');
      return;
    }

    try {
      // 并行发起两个请求,减少等待时间
      const [capitalRes, countryName] = await Promise.all([
        fetch(`https://restcountries.com/v3.1/name/${countryInput}?fields=capital`),
        getCountryName(countryInput)
      ]);

      if (!capitalRes.ok) throw new Error('首都信息请求失败');
      const capitalData = await capitalRes.json();
      // 用可选链避免数据不存在时报错
      const capital = capitalData[0]?.capital?.[0];

      if (!capital || !countryName) {
        setResult('Please enter a country.');
        return;
      }

      // 用状态更新页面内容
      setResult(`The capital of ${countryName} is ${capital}`);
    } catch (err) {
      console.error('搜索出错:', err);
      setResult('Please enter a country.');
    }
  }

  return (
    <>
      <button type="button" id="SearchButton" onClick={handleClick}>
        Search
      </button>
      {/* 用React状态渲染结果 */}
      <div id="output">{result}</div>
    </>
  );
}

关键修复点

  • 改用React的useState管理结果状态,完全遵循数据驱动视图的规则,彻底避免DOM操作带来的问题。
  • 用response.json()解析API响应,直接从对象中提取字段,再也不用担心JSON格式小变化导致的解析失败。
  • 加入try/catch处理网络请求错误,任何环节出错都会被捕获,不会导致程序崩溃。
  • 用Promise.all并行发起两个API请求,提升搜索速度。
  • 用可选链?.处理可能不存在的字段,避免因API返回数据结构变化抛出错误。

内容的提问来源于stack exchange,提问作者Jacob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 19:34:51