问题
I have a MarketOverview component that renders a bunch of cryptocurrency trading pair markets. On initialisation, I want it to render the BTC/USD market by default, which I'm doing via useEffect(). The problem is the defaultMarket gets called on every render. Moreover, defaultMarket depends on the tickers prop, so if I wrap it in useMemo(), then the eslint react-hooks plugin automatically populates tickers as a dependency.
Without useMemo():
const defaultMarket = tickers.find((ticker) => {
return ticker.market_id === "BTC-USD";
});
With useMemo():
const defaultMarket = useMemo(
() =>
tickers.find((ticker) => {
return ticker.market_id === "BTC-USD";
}),
[tickers]
);
Entire component:
export const MarketOverview = memo(({ tickers }: TProps) => {
// Set default market on initialisation to BTC/USD
const defaultMarket = tickers.find((ticker) => {
return ticker.market_id === "BTC-USD";
});
const [selectedMarket, setSelectedMarket] = useState<ITicker | undefined>(
undefined
);
useEffect(() => {
setSelectedMarket(defaultMarket);
}, [defaultMarket]);
// Select market
const selectMarket = (market: ITicker) => {
history.push(`${PUBLIC_URL}/markets/${market.market_id}`);
setSelectedMarket(market);
};
return (
<div className="market-overview-container">
<MarketSelector
tickers={tickers}
selectMarket={selectMarket}
selectedMarket={selectedMarket}
/>
{selectedMarket && <MarketStats selectedMarket={selectedMarket} />}
</div>
);
});
回答1:
Why, then you'll never recompute defaultMarket if tickers ever updates.
If you really want to though, you can add an eslint disable for the line and use an empty dependency array so the hook runs once only on component mount.
const defaultMarket = useMemo(
() =>
tickers.find((ticker) => {
return ticker.market_id === "BTC-USD";
}),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
来源:https://stackoverflow.com/questions/62057343/want-to-set-state-once-on-first-render-without-causing-uneccessary-re-renders-on