[英]How to handle react History.Push() causing undesired component remounts?
問題
在組件內部調用history.push()
似乎會導致整個 react 組件卸載和重新安裝; 導致毫無意義的遠程服務調用。
具體來說,我有一個在組件條目上觸發的遠程服務調用。 我不希望組件重新安裝,也不希望服務調用重新運行(它很慢)。
好像history.push(location.pathname + '?' + encodeURI(urlSearchParams.toString()));
無論如何都會導致卸載。 我使用不正確嗎? 是否有更好的方法來跟蹤用戶過濾器更改的歷史,而不必擔心無關的服務調用?
意圖
我正在利用history.push()
來保持瀏覽器歷史記錄隨着查詢參數的更改而更新。 查詢參數控制表數據的過濾,例如?sort=asc&isCompleted=true等。
當用戶更改過濾設置時,我打算對存儲在 state 中的現有表數據進行簡單過濾,而不是遠程重新加載數據並強迫用戶坐等。 我還希望用戶能夠與包含適當過濾器的其他用戶共享 URL。
我試過的
組件代碼
import React, { useEffect, useState } from 'react';
import { useLocation, useHistory } from 'react-router-dom';
function useQuery() {
return new URLSearchParams(useLocation().search);
}
export const WidgetTable = () => {
let urlSearchParams = useQuery();
let history = useHistory();
let location = useLocation();
const [originalTableData, setOriginalTableData] = useState<TableData| undefined>(undefined);
const [filteredTableData, setFilteredTableData] = useState<TableData| undefined>(undefined);
// go get the table data from the remote service
const fetchTableData = async () => {
<- go remotely fetch table data and then set originalTableData ->
}
// triggered when a user sets a filter on the table (updates the data displayed in the table)
const filterTableData = () => {
<- filter the existing table data in state and then set the filterdTableData ->
}
// also triggered when a user sets a filter on the table (updates the URL in the browser)
const setFilter = (filterToSet: ReleasePlanFilterType, value: string) => {
switch (filterToSet) {
case ReleasePlanFilterType.Target: {
if (urlSearchParams.get(filterToSet)) {
urlSearchParams.set(filterToSet, value);
} else {
urlSearchParams.append(filterToSet, value);
}
break;
}
<snip>
}
// We've set the filter in the query params, but persisting this to the history causes a reload :(
history.push(location.pathname + '?' + encodeURI(urlSearchParams.toString()));
}
useEffect(() => {
fetchTableData();
}, []);
return (<snip> a fancy table and filtering controls <snip>);
}
據我所知,在閱讀了其他幾個類似的堆棧溢出問題之后,似乎沒有辦法不重新安裝(重新渲染)組件。 歷史更改會自動導致 react 路由器 dom 如何處理幕后事務的 prop 更改。 我發現這些問題中的大多數都使用了 class 組件,答案是使用 shouldComponentUpdate 來查看以前的路徑是否等於新路徑。 如果他們是平等的,那么他們就會回來,基本上是這樣他們就不會重新渲染。
shouldComponentUpdate: function(nextProps, nextState) {
if(this.props.route.path == nextProps.route.path) return false;
return true;
}
來源: 防止 react-router history.push 重新加載當前路線
所以現在的問題是將其轉換為使用鈎子。 我需要運行一些測試,但我相信這應該適用於您的用例。
useEffect(() => {
fetchTableData();
}, [location.pathname]);
通過將location.pathname
添加為依賴項,只有在路徑名實際更改時才應調用此效果。
經過數小時的調試,我設法通過使用以下方法解決了這個問題:
<Route exact path="/">
<Home />
</Route>
代替:
<Route exact path="/" component={Home} />
這適用於react-router
v5。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.