Если компонент отображается. Я хочу открыть новую вкладку. (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>;
}
(работает, но не похоже на хорошее решение)
Похоже, вы имели в виду useEffect
вместо useMemo
.
Вы можете создать этот пользовательский хук 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>;
}
Отвечает ли это на ваш вопрос? Window.open открывает 2 одинаковых окна