Реагировать - открыть новую вкладку один раз

Если компонент отображается. Я хочу открыть новую вкладку. (window.open(url, "_blank")?.focus();) Но (во время разработки) эта вкладка открывается дважды из-за React.StrictMode. Как я могу предотвратить многократный вызов этого без отключения StrictMode?

Мои попытки:

function MyComp() {
    useMemo(() => window.open(url, "_blank")?.focus(), []);
    return <div>...</div>;
}

(не работает (вызывается дважды))

function MyComp() {
    useEffect(() => {
        const id = setTimeout(() => window.open(url, "_blank")?.focus(), 10);
        return () => clearTimeout(id);
    });
    return <div>...</div>;
}

(работает, но не похоже на хорошее решение)

Отвечает ли это на ваш вопрос? Window.open открывает 2 одинаковых окна

Harsh Gupta 30.03.2023 12:21

Похоже, вы имели в виду useEffect вместо useMemo.

Vaibhav Nigam 30.03.2023 12:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
2
81
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете создать этот пользовательский хук useEffectOnce в отдельном файле, который будет выполнять код только один раз, даже во время StrictMode:

// ./src/hooks/useEffectOnce.tsx

import { useEffect, useRef, useState } from 'react';

export const useEffectOnce = (effect: () => void | (() => void)) => {
  const effectFn = useRef<() => void | (() => void)>(effect);
  const destroyFn = useRef<void | (() => void)>();
  const effectCalled = useRef(false);
  const rendered = useRef(false);
  const [, setVal] = useState<number>(0);

  if (effectCalled.current) {
    rendered.current = true;
  }

  useEffect(() => {
    if (!effectCalled.current) {
      destroyFn.current = effectFn.current();
      effectCalled.current = true;
    }

    setVal(val => val + 1);

    return () => {
      if (!rendered.current) {
        return;
      }

      if (destroyFn.current) {
        destroyFn.current();
      }
    };
  }, []);
};

теперь вместо импорта useEffect из React импортируйте useEffectOnce из каталога, в котором вы сохранили хук, и выполните:

import { useEffectOnce } from "../hook/useEffectOnce" // <-- the path where you saved the hook

[...]

    useEffectOnce(() => {
        const id = setTimeout(() => window.open(url, "_blank")?.focus(), 10);
        return () => clearTimeout(id);
    });
Ответ принят как подходящий

Вам просто нужно отслеживать, открывали ли вы уже новую вкладку.

function MyComp() {
    const openedNewTabRef = useRef(false);

    useEffect(() => {
        if (!openedNewTabRef?.current) {
            window.open(url, "_blank")?.focus();
            openedNewTabRef.current = true;
        }
    }, []);

    return <div>...</div>;
}

Другие вопросы по теме