等待数组填充,然后渲染这些组件

时间:2020-01-13 15:34:35

标签: javascript node.js reactjs webpack async-await

我正在通过Firebase存储获取目录列表,然后完成后,返回要渲染的Project组件的列表,每个组件都具有以前检索的名称。您如何首先等待提取完成,然后返回相同数量的Project组件?

这是我尝试过的:

import React, {useState} from "react"
import "./index.css"
import {hot} from "react-hot-loader"
import Project from "./Project"
import firebase from "./Firebase.js"

function Projects(props){

    // Get refereance to firebase storage
    let storage = firebase.storage();
    // Reference the main projects folder
    let storageRef = storage.ref().child('projects');
    // Store all project names from firebase storage to then return them as Project components
    let projects = []

    // This lists the directories in 'Projects'
    storageRef.listAll().then(res => {
        // For each directory, push the name into the projects array
        res.prefixes.forEach((folderRef) => {
            projects.push(folderRef.name)
        })
    }).catch(error => {
            console.log(error)
    })

    return(
        <div>
            {projects.map(projName => (
                <>
                    <Project project={projName}/>
                </>

            ))}
        </div>
    )




}

export default hot(module)(Projects)

但是,当返回projects时,它为空,因为它没有等待forEach完成以上操作。另外,我认为projects.map()中的return语句不起作用。我尝试了Promise和Async Await,但是不确定如何构造它。

1 个答案:

答案 0 :(得分:2)

类似于类组件,您将需要使用功能组件中的useState钩子来定义state

此外,您应该使用useEffect钩子来处理HTTP请求的执行,以使它不会在每次重新渲染时都被触发。我们添加了一个空数组([])作为useEffect钩子的第二个参数,以使其仅运行一次,如官方的React钩子documentation所述。

返回响应后,我们通过调用setProjects()来更新状态。

function Projects(props){
  const [ projects, setProjects ] = useState([]);
  let storage = firebase.storage();
  let storageRef = storage.ref().child('projects');

  useEffect(() => {
    const response = []
    storageRef.listAll().then(res => {
    // For each directory, push the name into the projects array
      res.prefixes.forEach((folderRef) => {
        response.push(folderRef.name)
      })
      setProjects(response);
    }).catch(error => {
        console.log(error)
    })
  }, [])

  return(
    <div>
        {projects.length && projects.map((projName, index) => (               
           <Project project={projName} key={index} />
        ))}
    </div>
   )
}

export default hot(module)(Projects)