在我的主頁上,我有這樣的代碼
{selectedTab===0 && <XList allItemList={some_list/>}
{selectedTab===1 && <YList allItemList={some_list2/>}
現在,在 XList 中,我有這樣的事情:
{props.allItemList.map(item => <XItem item={item}/>)}
現在,在 XItem 內部,我正在呼叫 api 來獲取 XItem 的影像。
現在我的問題是在主頁中時,我將選項卡從 0 切換到 1 或從 1 切換到 0,它再次呼叫 XItem 中的所有 API。每當我切換選項卡時,它都會再次呼叫 api。我不想要那個。我已經在 XItem 中使用了 useEffect 并將 [] 陣列作為第二個引數。
我有我的后端代碼,我在其中制作了一個 api 來獲取 XItem 的影像。API 直接回傳影像而不是 url,所以我不能一次呼叫所有 api。
我需要一些解決方案,以便我可以最大限度地減少 api 呼叫。感謝幫助。
uj5u.com熱心網友回復:
基本問題是,通過選擇所選選項卡的方式,您正在安裝和卸載組件。重新安裝組件必然會重新運行任何useEffect發出網路請求并將任何結果存盤在本地組件狀態的安裝回呼。卸載組件必然會處理組件狀態。
{selectedTab === 0 && <XList allItemList={some_list} />}
{selectedTab === 1 && <YList allItemList={some_list2} />}
一種解決方案可能是將isActive道具傳遞給兩者XList并YList根據該selectedTab值設定值。每個組件根據isActiveprop有條件地呈現其內容。這個想法是保持組件安裝,以便它們在最初安裝時只獲取一次資料。
<XList allItemList={some_list} isActive={selectedTab === 0} />
<YList allItemList={some_list2} isActive={selectedTab === 1} />
例子 XList
const XList = ({ allItemList, isActive }) => {
useEffect(() => {
// expensive network call
}, []);
return isActive
? props.allItemList.map(item => <XItem item={item}/>)
: null;
};
替代方法包括將 API 請求和狀態提升到父組件并作為道具傳遞。或者使用 React 背景關系來做同樣的事情并通過背景關系提供狀態。或者實作/添加到像 Redux/Thunks 這樣的全域狀態管理。
uj5u.com熱心網友回復:
只是為了快速擴展Drew Reese的答案,請考慮讓您的選項卡成為選項卡組件的子項。這樣,您的組件(稍微)更加解耦。
const MyTabulator = ({ children }) => {
const kids = React.useMemo(() => React.Children.toArray(children), [children]);
const [state, setState] = React.useState(0);
return (
<div>
{kids.map((k, i) => (
<button key={k.props.name} onClick={() => setState(i)}>
{k.props.name}
</button>
))}
{kids.map((k, i) =>
React.cloneElement(k, {
key: k.props.name,
isActive: i === state
})
)}
</div>
);
};
和一個包裝器來處理 isActive 道具
const Tab = ({ isActive, children }) => <div hidden={!isActive}>{children}</div>
然后像這樣渲染它們
<MyTabulator>
<Tab name="x list"><XList allItemList={some_list} /></Tab>
<Tab name="y list"><YList allItemList={some_list2} /></Tab>
</MyTabulator>
uj5u.com熱心網友回復:
我對這個問題的看法。你可以用React.memo包裝XItem組件:
const XItem = (props) => {
...
}
const areEqual = (prevProps, nextProps) => {
/*
Add your logic here to check if you want to rerender XItem
return true if you don't want rerender
return false if you want a rerender
*/
}
export default React.memo(XItem, areEqual);
如果您選擇使用useMemo.
如果你想使用useCallback(我的默認選擇)只需要包裝你對 api 的呼叫。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/392144.html
標籤:javascript 反应 接口 反应钩子 使用效果
