如何从React中通过axios获得的数据表中渲染一个列表?

fivyi3re  于 5个月前  发布在  iOS
关注(0)|答案(2)|浏览(95)

我觉得这应该很简单,但我一直在努力,并希望得到一些帮助。
我试图从使用Axios获取的数据表中的字段生成一个下拉列表。数据表加载和渲染都很好,但React无法将列表识别为数组,因此无法Map项。数据表和列表都是在同一时间生成并存储在同一函数中的状态中。
下面是我的代码。任何关于如何做到这一点的建议都非常感谢。谢谢:

import React, {useState, useEffect} from 'react'
import db from './db.js' //<--I have my axios db connection in a seperate file

function App() {

  const [industryData, setIndustryData] = useState([]) //
  const [industryList, setIndustryList] = useState([]) //<--This is the list I want

  const getData= async(req, res)=>{
      const response = await db.get('/getTable/industries')
      const data =  response.data;
      console.log(data) // <--Data loads fine
      setIndustryData(data) // <--Data renders fine

      //I want to get a dropdown list from one of the fields in the data above
      let list = []
      data.forEach(row=>{
        list.push(row.industry)
      })
      console.log(list) //<--this works

      const industries = new Set(list)
      console.log(industries) //<---this works

      setIndustryList(industries) 
      console.log(industryList) //<--This is empty.
   }

  useEffect(()=>{
    getData()
  },[])

    return (
      <div className="App">
      
        //This is the dropdown I want but it's not working
        <select>
          {industryList.map(item=>(  //<---React doesn't recognize this object
            <option key={industryList.indexOf(item)}>{item}</option>
          ))}
        </select>

  
     //But rendering the original data table works.  But I don't want to do this because I don't get unique values.  I need a set.  Also it's just cleaner to use a list than an entire data set.
         <select>
            {industryData.map(item=>( //<---This works fine
              <option key={industryData.indexOf(item)}>{item.industry}</option>
            ))}
         </select>
    </div>
  );

字符串
}

export default App;

qf9go6mv

qf9go6mv1#

所以这里有两个问题在起作用。让我们首先从根本问题开始:

<select>
  {industryList.map(item=>(  //<---React doesn't recognize this object
    <option key={industryList.indexOf(item)}>{item}</option>
  ))}
</select>

字符串
map()不工作的原因是因为industryListSet

const industries = new Set(list)
setIndustryList(industries)


Set对象没有map()方法。(它们也没有indexOf()方法。)
如果你没有使用任何Set特性(除了在构造函数中删除重复值),最简单的解决方法是在将industries设置为state之前将其转换为数组。
这可以通过Array.from(industries)spreading将内容放入数组[...industries]中来完成。

setIndustryList(Array.from(industries))


如果你使用的是一些集合特性,你会想要做同样的转换,但是在渲染过程中。

<select>
  {Array.from(industryList).map((item, index) => (
    <option key={index}>{item}</option>
  ))}
</select>


Array.from()还允许我们传递第二个参数mapFn。这与map()的作用相同,但在Set到Array的转换期间进行。导致少一次迭代。

<select>
  {Array.from(industryList, (item, index) => (
    <option key={index}>{item}</option>
  ))}
</select>


现在,让我们继续讨论第二个问题,这个问题是在您尝试调试上面的代码时出现的。

setIndustryList(industries) 
console.log(industryList) //<--This is empty.


为什么industryList是空的?
让我们来看看useState的文档:

警告
  • set函数只更新 next render的state变量。如果在调用set函数后读取state变量,您仍然会获得调用前屏幕上的旧值。

当您在使用setIndustryList()后直接记录industryList时,它还没有保存它的新值。

vddsk6oq

vddsk6oq2#

看起来这个问题可能与getData函数的异步特性有关。当您调用setIndustryList(list)时,它可能不会立即更新industryData。您可以做的是,在getData而不是industryData.forEach中,您可以从data.foreach获取数据。这里是您可以使用的更新后的getData函数。

const getData= async(req, res)=>{
      const response = await db.get('/getTable/industries')
      const data =  response.data;
      console.log(data) // <--Data loads fine
      setIndustryData(data) // <--Data renders fine

      //I want to get a dropdown list from one of the fields in the data above
      let list = new Set()
      data.forEach(row=>{
        list.add(row.industry)
      })
      console.log(list) //<---this is empty for some reason.
      setIndustryList(list) //<--This is empty.
   }

字符串

相关问题