问题
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