如何在组件加载之前加载我的数据?

huangapple go评论70阅读模式
英文:

How can I load my data before the component is loaded?

问题

以下是您要翻译的代码部分:

import Navbar from '../../components/navbar/navbar'
import './playlist.css'
import { useEffect, useState } from 'react'
import album from '../../assets/album1.jpeg'
import { collection, getDocs, query, where } from 'firebase/firestore'
import { db, storage } from '../../config/firebase'
import { getDownloadURL, ref } from "firebase/storage";
import { useNavigate, useParams } from 'react-router'
import SongDetail from '../../components/song-detail/songDetail'

function Playlist() {
    const navigate = useNavigate();
    const { id } = useParams()
    const [dataBase, setDataBase] = useState()
    const [songDB, setSongDB] = useState([])
    const [count, setCount] = useState(0)
    const [Url, setUrl] = useState()
    useEffect(() => {
        const PlaylistCollectionRef = collection(db, "playlist")
        const fetchData = async () => {
            try {
                const q = query(PlaylistCollectionRef, where("PlaylistId", "==", id))
                const data = await getDocs(q)
                const filteredData = data.docs.map((doc) => ({ ...doc.data(), id: doc.id }))
                setDataBase(filteredData)
                if (filteredData) {
                    filteredData[0].Songs.map((data, i) => performDownload(data))
                    console.log("FILTER", filteredData)
                }
            } catch (error) {
                console.log(error)
            }
        }
        fetchData()
    }, [count])

    const performDownload = async (songID) => {
        const SongCollectionRef = collection(db, "music")
        const q = query(SongCollectionRef, where("SongId", "==", songID))
        const data = await getDocs(q)
        const filteredData1 = data.docs.map((doc) => ({ ...doc.data(), id: doc.id }))
        songDB.push({
            filteredData1
        })
        console.log("SONG DB", songDB)
        console.log("SONG NAME", songDB[0]?.filteredData1[0].SongName)
    }

    return (
        <div className="playlist-wrapper" id='playlist-id'>
            <div className="playlist-navbar">
                <Navbar />
            </div>
            <div className="playlist-main">
                <div className="playlist-main-section-1">
                    <div className="playlist-main-section-1-subsection">
                        <div className="playlist-section-1-back">
                            <button>BACK</button>
                        </div>
                        <div className="playlist-section-1-front">
                            <div className="playlist-subsection-images">
                                <div className="playlist-img-box">
                                    <img src={album} alt="" />
                                </div>
                            </div>
                            <div className="playlist-subsection-controls">
                                <div className="playlist-subsection-controls-name">
                                    <h1>MY PLAYLIST</h1>
                                </div>
                                <div className="playlist-subsection-controls-control">
                                    <button>Play</button>
                                    <button>Add</button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <div className="playlist-main-section-2">
                    <div className="playlist-playlist-subsection">
                        {
                            dataBase ?
                                dataBase[0].Songs.map((data, i) =>
                                    <SongDetail
                                        playlistId={id}
                                        albumId={data.albumId}
                                        num={i + 1}
                                        name={songDB[i * 2]?.filteredData1[0].SongName}
                                    />
                                )
                                : "LOADING"
                        }
                    </div>
                </div>
            </div>
        </div>
    )
}

export default Playlist

希望这对您有所帮助!

英文:

I am getting the data from the firebase database but am unable to show the data as the component is being executed first and then the data is being load. How can I fix this the proper way? The data loading part is working completely fine just that my map function is loading first and the data is loading after so it isn't being displayed.

import Navbar from &#39;../../components/navbar/navbar&#39;
import &#39;./playlist.css&#39;
import {useEffect, useState } from &#39;react&#39;
import album from &#39;../../assets/album1.jpeg&#39;
import { collection, getDocs ,query, where} from &#39;firebase/firestore&#39;
import { db ,storage} from &#39;../../config/firebase&#39;
import { getDownloadURL, ref } from &quot;firebase/storage&quot;;
import { useNavigate,useParams } from &#39;react-router&#39;
import SongDetail from &#39;../../components/song-detail/songDetail&#39;
function Playlist(){
const navigate = useNavigate();
const {id} = useParams()
const [dataBase, setDataBase]=useState()
const [songDB,setSongDB] = useState([])
const [count,setCount] =useState(0) 
// var dataBase = [1,2,3,4,5,6,7]
const [Url,setUrl] = useState()
useEffect(()=&gt;{
const PlaylistCollectionRef = collection(db, &quot;playlist&quot;)
const fetchData = async ()=&gt;{
try{
const q = query(PlaylistCollectionRef, where(&quot;PlaylistId&quot;, &quot;==&quot;, id))
const data = await getDocs(q)
// const data = await getDocs(PlaylistCollectionRef)
const filteredData = data.docs.map((doc)=&gt;({...doc.data(), id:doc.id}))
setDataBase(filteredData)
if(filteredData){
filteredData[0].Songs.map((data,i)=&gt; performDownload(data) )
console.log(&quot;FILTER&quot;,filteredData)
}
// handleDownload(filteredData[0].albumUrl)
}catch(error){
console.log(error)
}    
}
fetchData()
},[count])
// const downloadSongData = async()=&gt;{
//     if(dataBase?.length &gt; 0){
//         console.log(&quot;DB :: &quot;,dataBase)
//         dataBase[0].Songs.map((data,i)=&gt; performDownload(data) )
//         console.log(dataBase[0]?.Songs)
//     }
// }
const performDownload = async(songID)=&gt;{
const SongCollectionRef = collection(db, &quot;music&quot;)
const q = query(SongCollectionRef, where(&quot;SongId&quot;, &quot;==&quot;, songID))
const data = await getDocs(q)
// const data = await getDocs(PlaylistCollectionRef)
const filteredData1 = data.docs.map((doc)=&gt;({...doc.data(), id:doc.id}))
songDB.push({
filteredData1
})
console.log(&quot;SONG DB&quot;,songDB)
console.log(&quot;SONG NAME&quot;,songDB[0]?.filteredData1[0].SongName)
}
return(
&lt;div className=&quot;playlist-wrapper&quot; id=&#39;playlist-id&#39;&gt;
&lt;div className=&quot;playlist-navbar&quot;&gt;
&lt;Navbar/&gt;
&lt;/div&gt;
&lt;div className=&quot;playlist-main&quot;&gt;
&lt;div className=&quot;playlist-main-section-1&quot;&gt;
&lt;div className=&quot;playlist-main-section-1-subsection&quot;&gt;
&lt;div className=&quot;playlist-section-1-back&quot;&gt;
&lt;button&gt;BACK&lt;/button&gt;
&lt;/div&gt;
&lt;div className=&quot;playlist-section-1-front&quot;&gt;
&lt;div className=&quot;playlist-subsection-images&quot;&gt;
&lt;div className=&quot;playlist-img-box&quot;&gt;
&lt;img src={album} alt=&quot;&quot; /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div className=&quot;playlist-subsection-controls&quot;&gt;
&lt;div className=&quot;playlist-subsection-controls-name&quot;&gt;
&lt;h1&gt;MY PLAYLIST&lt;/h1&gt;
&lt;/div&gt;
&lt;div className=&quot;playlist-subsection-controls-control&quot;&gt;
&lt;button&gt;Play&lt;/button&gt;
&lt;button&gt;Add&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div className=&quot;playlist-main-section-2&quot;&gt;
&lt;div className=&quot;playlist-playlist-subsection&quot;&gt;
{
dataBase ?
dataBase[0].Songs.map((data,i)=&gt;
&lt;SongDetail 
playlistId = {id}
albumId = {data.albumId}
num = {i+1}
name = {songDB[i*2]?.filteredData1[0].SongName}
/&gt;
)
: &quot;LOADING&quot; 
}
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
)
}
export default Playlist

答案1

得分: 0

一旦您进入setDataBase()设置函数,您的组件应该使用新的状态值重新渲染,您确定在data.docs上进行映射后是否获得了正确的结果?
导致问题的第二个可能原因是,在performDownload()函数中,您直接通过将筛选后的结果推送到songDB状态来修改状态,这个操作的结果不会在应用程序UI中可见,您应该使用setSongDB设置器来使您的数据完全响应式。
回答这个问题 - 为了在浏览器输出屏幕之前加载数据,您可以使用useLayoutEffect钩子:https://react.dev/reference/react/useLayoutEffect,但我认为在您的情况下这并不是必要的。检查您的数据获取的结果是否是正确/已等待的格式,然后使用状态设置器来更新状态。

英文:

Once you go to setDataBase() setter function, your component should re-render with a new state value, are you sure that you are getting the right results after mapping on data.docs ?
The second thing that can cause your problem is that in performDownload() function you are modifying the state directly by pushing filtered results to the songDB state and the results of this operation will be not visible in the app UI, you should use setSongDB setter to make your data fully reactive.
Answering the question- in order to load your data before browser prints out the screen you can use useLayoutEffect hook: <https://react.dev/reference/react/useLayoutEffect>, but I think it's not necessary in your case. Check the results of your data fetching if they are in correct/awaited format and then use state setters to update a state.

huangapple
  • 本文由 发表于 2023年5月26日 13:54:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76337992.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定