国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

目錄
Next.js
Redux Connect
react-frontload
理論
第一次渲染
第二次渲染
App
更改 index.html 以添加數(shù)據(jù)
服務
服務端渲染和客戶端渲染在 React 中有什麼區(qū)別?
如何在我的客戶端渲染的 React 應用程序中發(fā)出服務器端請求?
為什麼我的全局變量在 React 中執(zhí)行兩次?
如何在服務端渲染的 React 中使用異步 API?
服務端渲染在 React 中有哪些好處?
如何在使用服務端渲染的 React 中的異步 API 時處理錯誤?
我可以在服務端渲染的 React 中使用鉤子嗎?
如何提高服務端渲染的 React 應用程序的性能?
如何測試我的服務端渲染的 React 應用程序?
我可以將服務端渲染與 Next.js 一起使用嗎?
首頁 web前端 js教程 處理服務器渲染的反應中的異步API

處理服務器渲染的反應中的異步API

Feb 16, 2025 am 11:52 AM

Dealing with Asynchronous APIs in Server-rendered React

要點總結(jié)

  • React 代碼的服務端渲染有助於縮短加載時間並提高 SEO 靈活性,但由於需要在知道所需數(shù)據(jù)之前渲染應用程序,因此處理異步 API 可能會面臨挑戰(zhàn)。
  • 現(xiàn)有的解決方案,例如 Next.js、Redux Connect 和 react-frontload,在處理服務端渲染的 React 代碼中的異步 API 時各有優(yōu)缺點。
  • 可以通過執(zhí)行兩次服務端渲染來實現(xiàn)自定義解決方案:第一次處理 API 調(diào)用和異步操作,第二次使用獲取的數(shù)據(jù)進行最終頁面渲染。
  • 自定義解決方案需要仔細處理組件中的不同狀態(tài),包括預取、後取、預渲染和後端渲染。這可以通過組件代碼中的複雜 if 語句來實現(xiàn)。
  • 自定義解決方案還需要更改 index.html 文件,以便將預取數(shù)據(jù)作為頁面請求的一部分發(fā)送,並將其添加到搜索和替換中。如果使用腳本標籤,則需要進行 base-64 編碼。

如果您曾經(jīng)製作過基本的 React 應用頁面,它可能會存在 SEO 差和性能問題,尤其是在較慢的設(shè)備上。您可以添加傳統(tǒng)的網(wǎng)頁服務端渲染(通常使用 NodeJS),但這並非一個簡單的過程,尤其是在處理異步 API 時。

服務端渲染代碼的兩個主要好處是:

  • 加快加載速度
  • 提高 SEO 靈活性

請記住,Google 會等待您的 JavaScript 加載,因此標題內(nèi)容等簡單內(nèi)容會無問題地更改。 (不過,我無法說明其他搜索引擎的情況,或者這有多可靠。)

在這篇文章中,我將討論在使用服務端渲染的 React 代碼時如何從異步 API 獲取數(shù)據(jù)。 React 代碼具有內(nèi)置於 JavaScript 中的整個應用程序結(jié)構(gòu)。這意味著,與具有控制器的傳統(tǒng) MVC 模式不同,您在應用程序渲染之前不知道需要什麼數(shù)據(jù)。使用像 Create React App 這樣的框架,您可以快速創(chuàng)建高質(zhì)量的工作應用程序,但它要求您僅在客戶端處理渲染。這存在性能問題,以及 SEO/數(shù)據(jù)問題,您可以在其中根據(jù)需要更改頭部。

問題

React 主要同步渲染,因此如果您沒有數(shù)據(jù),則會渲染加載屏幕並等待數(shù)據(jù)到來。這在服務器端效果不佳,因為您在渲染之前不知道需要什麼,或者您知道需要什麼,但您已經(jīng)渲染了。

查看此標準渲染方法:

ReactDOM.render(
  <provider> store={store}></provider>
    <browserrouter></browserrouter>
      <app></app>
    >
  >
, document.getElementById('root')
)

問題:

  1. 這是一個尋找根元素的 DOM 渲染。這在我的服務器上不存在,因此我們必須將其分開。
  2. 我們無法訪問主根元素之外的任何內(nèi)容。我們無法設(shè)置 Facebook 標籤、標題、描述、各種 SEO 標籤,並且我們無法控制元素外部的其餘 DOM,尤其是頭部。
  3. 我們提供了一些狀態(tài),但服務器和客戶端具有不同的狀態(tài)。我們需要考慮如何處理該狀態(tài)(在本例中為 Redux)。

因此,我在這裡使用了兩個庫,它們非常流行,因此希望它可以應用於您使用的其他庫。

Redux:存儲服務器和客戶端同步的狀態(tài)是一個噩夢般的問題。它非常昂貴,並且通常會導致複雜的錯誤。在服務器端,理想情況下,除了足以使事情正常工作並正確渲染之外,您不想使用 Redux 做任何事情。 (您仍然可以照常使用它;只需設(shè)置足夠的狀態(tài)使其看起來像客戶端。)如果您想嘗試,請查看各種分佈式系統(tǒng)指南作為起點。

React-Router:僅供參考,這是 v4 版本,這是默認安裝的版本,但如果您有較舊的現(xiàn)有項目,則會有很大不同。您需要確保在服務器端和客戶端處理路由,並且使用 v4——它在這方面非常出色。

畢竟,如果您需要進行數(shù)據(jù)庫調(diào)用怎麼辦?這突然成為一個大問題,因為它是非同步的,並且位於您的組件內(nèi)部。當然,這不是一個新問題:在官方 React 存儲庫中查看它。

您必須進行渲染才能確定需要哪些依賴項——這些依賴項需要在運行時確定——並在提供給客戶端之前獲取這些依賴項。

現(xiàn)有解決方案

下面,我將回顧當前提供的用於解決此問題的解決方案。

Next.js

在我們開始之前,如果您想要生產(chǎn)環(huán)境的服務端渲染的 React 代碼或通用應用程序,Next.js 是您的理想選擇。它有效、簡潔,並且有 Zeit 支持。

但是,它是有主見的,您必須使用他們的工具鏈,並且他們處理異步數(shù)據(jù)加載的方式不一定那麼靈活。

查看 Next.js 存儲庫文檔中的這段直接複製內(nèi)容:

ReactDOM.render(
  <provider> store={store}></provider>
    <browserrouter></browserrouter>
      <app></app>
    >
  >
, document.getElementById('root')
)

getInitialProps 是關(guān)鍵,它返回一個 promise,該 promise 解析為一個填充 props 的對象,並且僅在頁面上。最棒的是,這只是內(nèi)置到他們的工具鏈中:添加它即可工作,無需任何工作!

那麼如何獲取數(shù)據(jù)庫數(shù)據(jù)呢?您進行 API 調(diào)用。您不想?好吧,太糟糕了。 (好的,您可以添加自定義內(nèi)容,但您必須自己完全實現(xiàn)它。)但是,如果您考慮一下,這是一個非常合理且通常來說是良好的實踐,因為否則,您的客戶端仍然會進行相同的API 調(diào)用,並且服務器上的延遲幾乎可以忽略不計。

您還可以訪問的內(nèi)容受到限制——幾乎只是請求對象;同樣,這似乎是良好的實踐,因為您無法訪問您的狀態(tài),而您的狀態(tài)在服務器和客戶端上本來就不同。哦,如果您之前沒有註意到,它只適用於頂級頁面組件。

Redux Connect

Redux Connect 是一個非常有主見的服務器端渲染器,具有不錯的理念,但是如果您不使用他們描述的所有工具,這可能不適合您。此包有很多內(nèi)容,但它非常複雜,尚未升級到 React Router v4。有很多設(shè)置,但讓我們來看最重要的部分,只是為了學習一些經(jīng)驗教訓:

ReactDOM.render(
  <provider> store={store}></provider>
    <browserrouter></browserrouter>
      <app></app>
    >
  >
, document.getElementById('root')
)

裝飾器在 JavaScript 中不是標準的。在撰寫本文時,它們處於第 2 階段,因此請謹慎使用。這只是添加高階組件的另一種方式。這個想法很簡單:密鑰是傳遞給您的 props 的內(nèi)容,然後您有一系列 promise,它們會解析並傳入。這看起來不錯。也許另一種選擇就是這個:

import React from 'react'
export default class extends React.Component {
  static async getInitialProps ({ req }) {
    return req
      ? { userAgent: req.headers['user-agent'] }
      : { userAgent: navigator.userAgent }
  }
  render () {
    return <div>
      Hello World {this.props.userAgent}
    </div>
  }
}

使用 JavaScript 可以做到這一點,而且不會出現(xiàn)太多問題。

react-frontload

react-frontload 存儲庫沒有很多文檔或解釋,但我所能獲得的最佳理解可能來自測試(例如這個測試)和閱讀源代碼。當某些內(nèi)容被掛載時,它會被添加到 promise 隊列中,當該隊列解析時,它會被提供服務。它所做的事情非常好,儘管很難推薦一些沒有良好文檔、維護或使用的內(nèi)容:

// 1. 連接您的數(shù)據(jù),類似于 react-redux @connect
@asyncConnect([{
  key: 'lunch',
  promise: ({ params, helpers }) => Promise.resolve({ id: 1, name: 'Borsch' })
}])
class App extends React.Component {
  render() {
    // 2. 將數(shù)據(jù)作為 props 訪問
    const lunch = this.props.lunch
    return (
      <div>{lunch.name}</div>
    )
  }
}

尋找更好的解決方案

以上解決方案都沒有真正符合我對庫的靈活性和簡單性的期望,因此我現(xiàn)在將介紹我自己的實現(xiàn)。目標不是編寫包,而是讓您了解如何根據(jù)您的用例編寫自己的包。

此示例解決方案的存儲庫位於此處。

理論

其背後的想法相對簡單,儘管最終會產(chǎn)生相當多的代碼。這是為了概述我們正在討論的想法。

服務器必須渲染 React 代碼兩次,我們只會為此使用 renderToString。我們希望在第一次和第二次渲染之間保持上下文。在我們的第一次渲染中,我們試圖消除任何 API 調(diào)用、promise 和異步操作。在我們的第二次渲染中,我們希望獲取我們獲得的所有數(shù)據(jù)並將其放回我們的上下文中,從而渲染我們的工作頁面以進行分發(fā)。這也意味著應用程序代碼需要根據(jù)上下文執(zhí)行操作(或不執(zhí)行操作),例如是否在服務器上或瀏覽器上,以及在任一情況下是否正在獲取數(shù)據(jù)。

此外,我們可以根據(jù)需要自定義它。在本例中,我們根據(jù)上下文更改狀態(tài)代碼和頭部。

第一次渲染

在您的代碼中,您需要知道您是在服務器上還是在瀏覽器上工作,理想情況下,您希望對它進行複雜控制。使用 React Router,您可以獲得一個靜態(tài)上下文 prop,這很棒,所以我們將使用它。目前,我們只是添加了一個數(shù)據(jù)對象和請求數(shù)據(jù),正如我們從 Next.js中學到的那樣。我們的 API 在服務器和客戶端之間有所不同,因此您需要提供一個服務器 API,最好與您的客戶端 API 具有相似的接口:

ReactDOM.render(
  <provider> store={store}></provider>
    <browserrouter></browserrouter>
      <app></app>
    >
  >
, document.getElementById('root')
)

第二次渲染

在第一次渲染之後,我們將獲取那些掛起的 promise 並等待這些 promise 完成,然後重新渲染,更新上下文:

import React from 'react'
export default class extends React.Component {
  static async getInitialProps ({ req }) {
    return req
      ? { userAgent: req.headers['user-agent'] }
      : { userAgent: navigator.userAgent }
  }
  render () {
    return <div>
      Hello World {this.props.userAgent}
    </div>
  }
}

App

快速從我們的服務器跳轉(zhuǎn)到應用程序代碼:在我們?nèi)魏尉哂新酚善鬟B接的組件中,我們現(xiàn)在都可以獲得它:

// 1. 連接您的數(shù)據(jù),類似于 react-redux @connect
@asyncConnect([{
  key: 'lunch',
  promise: ({ params, helpers }) => Promise.resolve({ id: 1, name: 'Borsch' })
}])
class App extends React.Component {
  render() {
    // 2. 將數(shù)據(jù)作為 props 訪問
    const lunch = this.props.lunch
    return (
      <div>{lunch.name}</div>
    )
  }
}

哇,這有很多複雜的代碼。在這個階段,您可能想要採用更具中繼的方法,在該方法中,您將數(shù)據(jù)獲取代碼分離到另一個組件中。

此組件由您可能熟悉的組件構(gòu)成——渲染步驟和 componentWillMount 步驟。四階段 if 語句處理不同的狀態(tài)——預取、後取、預渲染和後端渲染。我們還在數(shù)據(jù)加載後添加到頭部。

最後,還有一個獲取數(shù)據(jù)步驟。理想情況下,您的 API 和數(shù)據(jù)庫具有相同的 API,這使得執(zhí)行相同。您可能希望將這些放入 Thunk 或 Saga 中的操作中,以使其更具可擴展性。

查看文章“服務端 React 渲染”和存儲庫 React 服務端渲染以了解更多信息。請記住,您仍然需要處理數(shù)據(jù)未加載的狀態(tài)!您只會在第一次加載時進行服務器端渲染,因此您將在後續(xù)頁面上顯示加載屏幕。

更改 index.html 以添加數(shù)據(jù)

我們需要將任何預取數(shù)據(jù)作為頁面請求的一部分發(fā)送,因此我們將添加一個腳本標籤:

@asyncConnect([{
  lunch: ({ params, helpers }) => Promise.resolve({ id: 1, name: 'Borsch' })
}])

服務

然後我們需要將其添加到我們的搜索和替換中。但是,HTML 使用非?;镜哪_本標籤查找器,因此如果您有腳本標籤,則需要對其進行 base-64 編碼。此外,不要忘記我們的頭部標籤!

const App = () => (
  <frontload>isServer</frontload>
    <component1> entityId='1' store={store}></component1>
  >
)

return frontloadServerRender(() => (
  render(<app></app>)
)).then((serverRenderedMarkup) => {
  console.log(serverRenderedMarkup)
})

我們還處理狀態(tài)代碼更改——例如,對於 404——因此,如果您有 404 頁面,您可以這樣做:

const context = {data: {}, head: [], req, api}
const store = configureStore()
renderToString(
  <provider> store={store}></provider>
    <staticrouter> location={req.url} context={context}>
      <app></app>
    >
  >
)

總結(jié)

如果您不確定自己在做什麼,只需使用 Next.js。它專為服務端渲染和通用應用程序而設(shè)計,或者如果您希望手動執(zhí)行所有操作的靈活性,則可以按照您想要的方式進行。一個例子可能包括您在子組件中而不是在頁面級別進行數(shù)據(jù)獲取。

希望本文能幫助您入門!不要忘記查看 GitHub 存儲庫以獲取可行的實現(xiàn)。

關(guān)於異步 API 和服務端渲染 React 的常見問題解答 (FAQ)

服務端渲染和客戶端渲染在 React 中有什麼區(qū)別?

服務端渲染 (SSR) 和客戶端渲染 (CSR) 是渲染網(wǎng)頁的兩種不同方法。在 SSR 中,服務器會響應請求生成頁面的完整 HTML,然後將其發(fā)送到客戶端。這會導致更快的初始頁面加載時間,並且有利於 SEO。但是,這可能會導致頁面轉(zhuǎn)換速度變慢,因為每次請求都需要渲染整個頁面。另一方面,CSR 意味著渲染是在瀏覽器中使用 JavaScript 進行的。這會導致初始頁面加載時間變慢,但頁面轉(zhuǎn)換速度更快,因為只需要重新渲染必要的組件。

如何在我的客戶端渲染的 React 應用程序中發(fā)出服務器端請求?

要在客戶端渲染的 React 應用程序中發(fā)出服務器端請求,您可以使用 fetch API 或 axios 等庫。您可以在 componentDidMount 生命週期方法中或在使用函數(shù)組件時在 useEffect 掛鉤內(nèi)發(fā)出請求。然後可以將響應設(shè)置為狀態(tài)並在您的組件中使用。

為什麼我的全局變量在 React 中執(zhí)行兩次?

這可能是由於 React 批處理狀態(tài)更新的方式造成的。如果您在 React 組件內(nèi)更新全局變量,則由於 setState 的異步性質(zhì),它可能會更新兩次。為避免這種情況,您可以使用 setState 的函數(shù)形式,這可以確保狀態(tài)更新基於先前狀態(tài),而不是當前狀態(tài)。

如何在服務端渲染的 React 中使用異步 API?

要在服務端渲染的 React 中使用異步 API,您可以在服務器端代碼中使用 async/await 語法。這允許您在渲染頁面之前等待 API 響應。您可以使用 axios 等庫來發(fā)出 API 請求。

服務端渲染在 React 中有哪些好處?

服務端渲染在 React 中有很多好處。它提高了初始頁面加載時間,這可以帶來更好的用戶體驗。它還提高了 SEO,因為搜索引擎爬蟲可以更容易地索引服務端渲染的內(nèi)容。此外,它允許更一致的初始狀態(tài),因為相同的代碼在服務器和客戶端上運行。

如何在使用服務端渲染的 React 中的異步 API 時處理錯誤?

您可以使用 try/catch 塊在異步函數(shù)中處理錯誤。這允許您捕獲在發(fā)出 API 請求時發(fā)生的任何錯誤並適當?shù)靥幚硭鼈儯缤ㄟ^渲染錯誤消息。

我可以在服務端渲染的 React 中使用鉤子嗎?

是的,您可以在服務端渲染的 React 中使用鉤子。但是,請記住,鉤子只能在函數(shù)組件中使用,而不能在類組件中使用。此外,某些鉤子(例如 useEffect)不會在服務器上運行,因此您需要確保您的代碼可以處理這種情況。

如何提高服務端渲染的 React 應用程序的性能?

提高服務端渲染的 React 應用程序性能的方法有很多。您可以使用代碼分割,只為每個頁面加載必要的代碼。您還可以使用緩存來避免重新渲染未更改的頁面。此外,優(yōu)化服務器端代碼可以幫助提高性能。

如何測試我的服務端渲染的 React 應用程序?

您可以使用 Jest 和 React Testing Library 等測試庫來測試您的服務端渲染的 React 應用程序。這些庫允許您隔離測試組件並確保它們正確渲染。

我可以將服務端渲染與 Next.js 一起使用嗎?

是的,Next.js 是一個用於 React 的框架,它開箱即用地支持服務端渲染。它提供了一個簡單的服務端渲染 API,還支持靜態(tài)站點生成和客戶端渲染。

以上是處理服務器渲染的反應中的異步API的詳細內(nèi)容。更多資訊請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

本網(wǎng)站聲明
本文內(nèi)容由網(wǎng)友自願投稿,版權(quán)歸原作者所有。本站不承擔相應的法律責任。如發(fā)現(xiàn)涉嫌抄襲或侵權(quán)的內(nèi)容,請聯(lián)絡(luò)admin@php.cn

熱AI工具

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅(qū)動的應用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6

Dreamweaver CS6

視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Java vs. JavaScript:清除混亂 Java vs. JavaScript:清除混亂 Jun 20, 2025 am 12:27 AM

Java和JavaScript是不同的編程語言,各自適用於不同的應用場景。 Java用於大型企業(yè)和移動應用開發(fā),而JavaScript主要用於網(wǎng)頁開發(fā)。

JavaScript評論:簡短說明 JavaScript評論:簡短說明 Jun 19, 2025 am 12:40 AM

JavascriptconcommentsenceenceEncorenceEnterential gransimenting,reading and guidingCodeeXecution.1)單inecommentsareusedforquickexplanations.2)多l(xiāng)inecommentsexplaincomplexlogicorprovideDocumentation.3)

如何在JS中與日期和時間合作? 如何在JS中與日期和時間合作? Jul 01, 2025 am 01:27 AM

JavaScript中的日期和時間處理需注意以下幾點:1.創(chuàng)建Date對像有多種方式,推薦使用ISO格式字符串以保證兼容性;2.獲取和設(shè)置時間信息可用get和set方法,注意月份從0開始;3.手動格式化日期需拼接字符串,也可使用第三方庫;4.處理時區(qū)問題建議使用支持時區(qū)的庫,如Luxon。掌握這些要點能有效避免常見錯誤。

為什麼要將標籤放在的底部? 為什麼要將標籤放在的底部? Jul 02, 2025 am 01:22 AM

PlacingtagsatthebottomofablogpostorwebpageservespracticalpurposesforSEO,userexperience,anddesign.1.IthelpswithSEObyallowingsearchenginestoaccesskeyword-relevanttagswithoutclutteringthemaincontent.2.Itimprovesuserexperiencebykeepingthefocusonthearticl

JavaScript與Java:開發(fā)人員的全面比較 JavaScript與Java:開發(fā)人員的全面比較 Jun 20, 2025 am 12:21 AM

JavaScriptIspreferredforredforwebdevelverment,而Javaisbetterforlarge-ScalebackendsystystemsandSandAndRoidApps.1)JavascriptexcelcelsincreatingInteractiveWebexperienceswebexperienceswithitswithitsdynamicnnamicnnamicnnamicnnamicnemicnemicnemicnemicnemicnemicnemicnemicnddommanipulation.2)

JavaScript:探索用於高效編碼的數(shù)據(jù)類型 JavaScript:探索用於高效編碼的數(shù)據(jù)類型 Jun 20, 2025 am 12:46 AM

javascripthassevenfundaMentalDatatypes:數(shù)字,弦,布爾值,未定義,null,object和symbol.1)numberSeadUble-eaduble-ecisionFormat,forwidevaluerangesbutbecautious.2)

什麼是在DOM中冒泡和捕獲的事件? 什麼是在DOM中冒泡和捕獲的事件? Jul 02, 2025 am 01:19 AM

事件捕獲和冒泡是DOM中事件傳播的兩個階段,捕獲是從頂層向下到目標元素,冒泡是從目標元素向上傳播到頂層。 1.事件捕獲通過addEventListener的useCapture參數(shù)設(shè)為true實現(xiàn);2.事件冒泡是默認行為,useCapture設(shè)為false或省略;3.可使用event.stopPropagation()阻止事件傳播;4.冒泡支持事件委託,提高動態(tài)內(nèi)容處理效率;5.捕獲可用於提前攔截事件,如日誌記錄或錯誤處理。了解這兩個階段有助於精確控制JavaScript響應用戶操作的時機和方式。

Java和JavaScript有什麼區(qū)別? Java和JavaScript有什麼區(qū)別? Jun 17, 2025 am 09:17 AM

Java和JavaScript是不同的編程語言。 1.Java是靜態(tài)類型、編譯型語言,適用於企業(yè)應用和大型系統(tǒng)。 2.JavaScript是動態(tài)類型、解釋型語言,主要用於網(wǎng)頁交互和前端開發(fā)。

See all articles