我正在嘗試實作一個回應式搜索欄,用于過濾純組件串列(一次最多顯示 100 個組件)。但是,在鍵入首字母和讓它顯示在搜索欄中以及其下方呈現的組件串列之間有半秒的凍結時間。我相信是渲染組件的數量導致了這種延遲,因為將渲染量限制為 ~20 會使回應幾乎是即時的。
我有哪些選擇可以最大程度地減少這種延遲并創建幾乎即時的渲染?
我看過延遲加載,但我只能找到基于用戶滾動動態加載的方法。有沒有一種方法可以隨著時間的推移拆分串列的渲染,這樣就不會出現長時間的停頓?
我也看過React.memo但延遲是當我從 0 -> 100 個組件開始時,所以在初始加載后快取并沒有真正的幫助。有沒有辦法將這些組件預加載到快取中?
const SearchPage = ({ dataMap }) => {
const [searchResults, setSearchResults] = useState([]);
const onInput = (e) => {
// near instant response when limit is ~20
setSearchResults(searchIndex.search(e.target.value, { limit: 100 }));
};
return (
<div>
<SearchBar onInput={onInput} />
<DataListTable
dataList={searchResults.map((dataId) => (dataMap[dataId]))}
/>
</div>
);
};
const DataListTable = ({ dataList }) => (
<table className="table">
<thead>
<tr>
<th>Inputs</th>
<th>Outputs</th>
<th>Requirement</th>
</tr>
</thead>
<tbody>
{dataList.map((data) => (
<DataRow data={data} key={data.dataId} />
))}
</tbody>
</table>
);
const DataRow = ({ data }) => {}
export default memo(DataRow);
uj5u.com熱心網友回復:
我可以向您建議幾件事,但請記住,我不確定它是否肯定會提高您的組件的性能。
- 您的
SearchPage組件被耦合以處理您的searchResults資料更新。我認為這可能會導致性能問題,并且從軟體設計原則(確切地說是單一職責原則)來看,它看起來設計得很糟糕。在這種情況下,我會做的是將 移動state到您的DataListTable組件,而是將搜索值作為屬性傳遞給它:
const DataListTable = ({ search }) => {
const [searchResults, setSearchResults] = useState([]);
useEffect(() => {
setSearchResults(searchIndex.search(search, { limit: 100 }));
}, [search]);
return (
<table className="table">
<thead>
<tr>
<th>Inputs</th>
<th>Outputs</th>
<th>Requirement</th>
</tr>
</thead>
<tbody>
{searchResults.map((data) => (
<DataRow data={data} key={data.dataId} />
))}
</tbody>
</table>
);
};
那么你SearchPage可能看起來像這樣:
const SearchPage = () => {
const [search, setSearch] = useState('');
const onInput = (e) => {
setSearch(e.target.value);
};
return (
<div>
<SearchBar onInput={onInput} />
<DataListTable search={search} />
</div>
);
};
- 關于您的
dataMap物件:我認為您應該在收到來自 API 端點的結果后映射物件。您不應該直接在組件內部進行資料映射。你可以在你的searchIndex.search方法中做到這一點。一個假設的例子是:
搜索服務.js
export const search = async (term, options) => {
const response = await api.getDataListTableData(term, options);
const mappedResponse = response.map((x) => ({
id: x._id,
name: `${x.first_name} ${x.last_name}`,
}));
return mappedResponse;
};
然后只需在DataListTable組件內部呼叫它:
import * as searchIndex from './searchService';
useEffect(() => {
searchIndex.search(search, { limit: 100 }).then((data) => setSearchResults(data));
}, [search]);
- 您可以做的另一件事是對搜索結果進行去抖動,因為如果不對其進行去抖動,可能會導致 2 個缺點:
- 您的 API 承受著不必要的呼叫
- 您的
DataListTable組件負擔了不必要的重新渲染
為了去抖動,你可以使用這個useDebounce鉤子,取自這篇文章:
const useDebounce = (value, timeout) => {
// Save a local copy of `value` in this state which is local to our hook
const [state, setState] = useState(value);
useEffect(() => {
// Set timeout to run after delay
const handler = setTimeout(() => setState(value), timeout);
// clear the setTimeout listener on unMount
return () => clearTimeout(handler);
}, [value, timeout]);
return state;
};
然后只需使用組件的useDebounce內部SearchPage:
const SearchPage = () => {
const [search, setSearch] = useState('');
const debouncedSearchQuery = useDebounce(search, 500);
const onInput = (e) => {
setSearch(e.target.value);
};
return (
<div>
<SearchBar onInput={onInput} />
<DataListTable search={debouncedSearchQuery} />
</div>
);
};
我希望其中一些事情會被證明是有幫助的。祝你好運!
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/401768.html
標籤:javascript 反应 搜索 下一个.js 延迟加载
