簡體   English   中英

如何將 UI 更新推送到 javascript 前端?

[英]How do you push a UI update to a javascript frontend?

所以我正在構建一個簡單的反應應用程序,它獲取一堆圖像並將它們顯示為卡片。

目的是顯示一條信息消息,直到所有圖像都加載完畢,然后再次刪除通知。

const App = () => {
  const [cardInfo, setCardInfo] = useContext(CardInfoContext)

  useEffect(() => {
    fetchData(setCardInfo)
  }, [])

  useEffect(() => {
    const app = document.querySelector('.app')
    for(const child of app.children){
      app.removeChild(child)
    }

    const loadingNotice = document.createElement('h1')
    loadingNotice.innerHTML = "Fetching data ..."
    app.appendChild(loadingNotice) //<-- this never shows up

    cardInfo.forEach( info => {
      const img = document.createElement('img')
      img.src = info.image
      app.appendChild(img)
    })

    app.removeChild(loadingNotice)

  }, [cardInfo])
  
  return (
    <>
      <div className="app">
        <h1>Fetching data...</h1>
      </div>
    </>
)};

相反,應用程序會一直保持空白,直到所有圖像都加載完畢,然后一次顯示所有圖像——但從來沒有加載通知。

我可以以某種方式將加載指示器更改“推送”到獨立於渲染的 rest 的 UI 嗎?

我嘗試的另一件事是

const App = () => {
  const [cardInfo, setCardInfo] = useContext(CardInfoContext)

  useEffect(() => {
    fetchData(setCardInfo)
  }, [])

  useEffect(() => {
    const app = document.querySelector('.app')
    if(!cardInfo) return

    const loadingNotice = app.querySelector(".loadingNotice")
    loadingNotice.style.display = 'block' //<-- this never shows up

    cardInfo.forEach( info => {
      const img = document.createElement('img')
      img.src = info.image
      app.appendChild(img)
    })

    loadingNotice.style.display = 'none'

  }, [cardInfo])
  
  return (
    <>
      <div className="app">
        <h1 className="loadingNotice">Fetching data...</h1>
      </div>
    </>
)}

這將是不正確的,因為我確實需要刪除所有圖像,至少,但即使只顯示加載通知幾分之一秒,然后組件變為空白,直到可以顯示所有圖像。

useEffect觀察cardInfo何時更改,而不是渲染觸發后發生的時間。 您可以改用useLayoutEffect

...但它會在所有 DOM 突變后同步觸發。 使用它從 DOM 中讀取布局並同步重新渲染。 在 useLayoutEffect 中安排的更新將在瀏覽器有機會繪制之前同步刷新。

順便說一句,我不會將直接 DOM 操作與 React 結合起來以避免這樣的問題(以及其他原因)

就像是

const App = () => {
  const [isLoadgin, setIsLoading] = useState(true)
  const [cardInfo, setCardInfo] = useContext(CardInfoContext)

  useEffect(() => {
    fetchData(result => {
      setCardInfo(result);
      setIsLoading(false);
    })
  }, [])
    
  return (
    <>
      <div className="app">
        {isLoading && <h1 className="loadingNotice">Fetching data...</h1>}
        {
          cardInfo.map(card => <img src={card.image} />)
        }
      </div>
    </>
)}

您需要條件渲染,而不是在 useEffect 中嘗試的所有 DOM 操作。

...
return(
<>
  <div className="app">
    { !cardInfo ? <h1 className="loadingNotice">Fetching data...</h1> : <Cards info={cardInfo} /> }

  </div>
</>

)

注意:我假設您有類似<Cards>組件來顯示卡片詳細信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM