【问题标题】:ReactJS crashes when mapping over array being called from API and returning undefined映射从 API 调用的数组并返回未定义时,ReactJS 崩溃
【发布时间】:2019-09-20 08:03:18
【问题描述】:

我正在学习 ReactJS 并构建一个从 API 获取数据并将其呈现在页面上的小应用程序。我有一个包含区域列表的侧边栏,并进行 API 调用以在单击时检索该区域中的所有国家/地区。

    function getOccurrence(array, value) {
      return array.filter((v) => (v === value)).length;
    }

    let uniqueRegions = totalRegions.filter((v, i, a) => a.indexOf(v) === i);

    let lis = [];
    for (let i = 0; i < uniqueRegions.length -1; i++) {
      lis.push(
        <li className="nav-item" key={i} onClick={props.sideBar}>
          <span className="nav-link bg-success mb-1"><strong>{uniqueRegions[i]}</strong> - {getOccurrence(totalRegions, uniqueRegions[i])}</span>
          <ul>
          {this.props.regionData.map((country, index) => <li key={index}>{country.name}</li>) || null}
          </ul>
        </li>

      )

    }

但是,初始点击会调用该函数并返回一个未定义的数组。当映射到短暂未定义的数组时,它会使应用程序崩溃。我想映射数组并为数组中的每个项目返回一个 li。

我已尝试有条件地渲染所需元素 {country.name} 并在数组未定义时返回 null,但在定义数组时,所需元素不会渲染。下面是点击时运行的函数,以及设置区域数据状态的回调函数。

  sideBarData = () => {
    let totalRegions = this.state.nations.map(a => a.region)
    function getOccurrence(array, value) {
      return array.filter((v) => (v === value)).length;
    }
    let uniqueRegions = totalRegions.filter((v, i, a) => a.indexOf(v) === i);
    for (let i = 0; i < uniqueRegions.length -1; i++) {
      this.setState({
        regionData: this.findAllByRegion(uniqueRegions[i])
      })
    }
  }

  findAllByRegion = (region) =>{
    return Axios
     .get('https://restcountries.eu/rest/v2/region/' + region)
     .then(res => {
       if(res.status === 200 && res !== null){
        this.setState(prevState =>({
          regionData: res.data
        }))
         console.log(this.state.regionData);
       } else {
         throw new Error('No country found');
       }
       })
       .catch(error => {
         console.log(error)
         return []
       });
   };

我希望 {this.props.regionData.map((country, index) =&gt; &lt;li key={index}&gt;{country.name}&lt;/li&gt;) || null} 行在数组未定义时为空,但 DOM 在定义数组时不会更新 li。

【问题讨论】:

    标签: reactjs undefined conditional-rendering


    【解决方案1】:

    只需检查您是否从您设置状态的 api 获取有效数据,在您的 findAllByRegion 中执行以下操作

    this.setState(prevState =>({
      // always validate your response.
      // if res is undefined doing res.data will crash your app
       regionData: res && res.data || []  
    }))
    

    【讨论】:

    • 我已经将 regionData 初始化为一个空数组:state = {regionData: []}
    • 是的,但是来自 api 的数据可以是未定义的,这将覆盖您的状态。如果res.data 未定义,您的regionData 将未定义
    • 啊,我明白了。现在我在引用`return array.filter 时收到一条错误消息Cannot read property 'filter' of undefined
    • 你在哪里设置state.nations?或者你将什么传递给函数getOccurrence
    • 我让它工作了!你的问题让我重新审视了我是如何将道具传递给子组件的。我传递的是 this.variable 而不是变量本身,这就是未定义道具的原因。非常感谢!
    【解决方案2】:

    你不能使用undefined.map。在通过它进行映射之前,您需要确保该值是一个数组。

    例如:

       function getOccurrence(array, value) {
          return array.filter((v) => (v === value)).length;
        }
    
        let uniqueRegions = totalRegions.filter((v, i, a) => a.indexOf(v) === i);
    
        let lis = [];
    
        // this next line here makes sure you always have an array
        const regionData = this.props.regionData || [];
    
        for (let i = 0; i < uniqueRegions.length -1; i++) {
          lis.push(
            <li className="nav-item" key={i} onClick={props.sideBar}>
              <span className="nav-link bg-success mb-1"><strong>{uniqueRegions[i]}</strong> - {getOccurrence(totalRegions, uniqueRegions[i])}</span>
              <ul>
              {/* never undefined */regionData.map((country, index) => <li key={index}>{country.name}</li>) || null}
              </ul>
            </li>
          )
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-10
      相关资源
      最近更新 更多