競速條件

競速條件

雖然不可能完全消除應用程式中所有可能的競速條件,但 React Router 會自動處理網頁使用者介面中最常見的競速條件。

瀏覽器行為

React Router 處理網路並發的方式,很大程度上受到網頁瀏覽器處理文件行為的啟發。

考慮點擊一個連結到新文件,然後在新頁面完成載入之前點擊另一個不同的連結。瀏覽器將會

  1. 取消第一個請求
  2. 立即處理新的導航

相同的行為適用於表單提交。當一個待處理的表單提交被新的提交中斷時,第一個提交會被取消,而新的提交會立即被處理。

React Router 行為

就像瀏覽器一樣,使用連結和表單提交的中斷導航將取消正在進行的資料請求,並立即處理新的事件。

Fetchers 稍微複雜一些,因為它們不像導航那樣是單例事件。Fetchers 無法中斷其他 fetcher 實例,但它們可以中斷自身,並且行為與其他所有情況相同:取消中斷的請求並立即處理新的請求。

然而,Fetchers 在重新驗證方面確實會相互交互。在 fetcher 的動作請求返回瀏覽器後,會發送所有頁面資料的重新驗證。這表示可能同時有多個重新驗證請求正在進行中。React Router 將提交所有「新鮮」的重新驗證回應,並取消任何過時的請求。過時的請求是指任何開始時間*早於*已返回的請求。

這種網路管理方式可以防止由網路競速條件引起的最常見 UI 錯誤。

由於網路是不可預測的,而且您的伺服器仍然會處理這些已取消的請求,因此您的後端可能仍然會遇到競速條件,並存在潛在的資料完整性問題。這些風險與使用純 HTML `<forms>` 的預設瀏覽器行為的風險相同,我們認為這些風險很低,並且超出 React Router 的範圍。

實際優點

考慮建構一個預輸入下拉式方塊。當使用者輸入時,您會向伺服器發送請求。當他們輸入每個新字元時,您會發送一個新的請求。重要的是不要向使用者顯示不再在文字欄位中的值之結果。

當使用 fetcher 時,這會自動為您管理。考慮以下虛擬碼

// route("/city-search", "./search-cities.ts")
export async function loader({ request }) {
  const { searchParams } = new URL(request.url);
  return searchCities(searchParams.get("q"));
}
export function CitySearchCombobox() {
  const fetcher = useFetcher();

  return (
    <fetcher.Form action="/city-search">
      <Combobox aria-label="Cities">
        <ComboboxInput
          name="q"
          onChange={(event) =>
            // submit the form onChange to get the list of cities
            fetcher.submit(event.target.form)
          }
        />

        {fetcher.data ? (
          <ComboboxPopover className="shadow-popup">
            {fetcher.data.length > 0 ? (
              <ComboboxList>
                {fetcher.data.map((city) => (
                  <ComboboxOption
                    key={city.id}
                    value={city.name}
                  />
                ))}
              </ComboboxList>
            ) : (
              <span>No results found</span>
            )}
          </ComboboxPopover>
        ) : null}
      </Combobox>
    </fetcher.Form>
  );
}

fetcher.submit 的呼叫將自動取消該 fetcher 上的待處理請求。這確保您永遠不會向使用者顯示針對不同輸入值的請求結果。

文件與範例 CC 4.0