Хотите установить состояние один раз при первом рендеринге, не вызывая лишних повторных рендеров при последующих обновлениях

У меня есть MarketOverviewкомпонент, который отображает множество парных рынков для торговли криптовалютой. При инициализации я хочу, чтобы он отображалBTC/USD рынок по умолчанию, что я делаю через useEffect(). Проблема в томdefaultMarketвызывается при каждом рендере. Кроме того,defaultMarket зависит от tickers опора, поэтому, если я заверну его в useMemo(), то плагин eslint react-hooks автоматически заполняет tickers как зависимость.

Без useMemo():

const defaultMarket = tickers.find((ticker) => {
    return ticker.market_id === "BTC-USD";
  });

С участием useMemo():

const defaultMarket = useMemo(
    () =>
      tickers.find((ticker) => {
        return ticker.market_id === "BTC-USD";
      }),
    [tickers]
  );

Весь компонент:

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 ответ

Решение

Почему тогда ты никогда не пересчитаешь defaultMarket если tickers когда-либо обновляется.

Если вы действительно хотите, вы можете добавить отключение eslint для строки и использовать пустой массив зависимостей, чтобы ловушка запускалась один раз только при монтировании компонента.

const defaultMarket = useMemo(
  () =>
    tickers.find((ticker) => {
      return ticker.market_id === "BTC-USD";
    }),
  // eslint-disable-next-line react-hooks/exhaustive-deps
  []
);
Другие вопросы по тегам