Я сделал пару изменений в коде.
- Я использую
useRef
для хранения статуса компонента. Таким образом, в useEffect
я проверяю, смонтирован ли компонент, а затем устанавливаю значение таймера из localStorage
или из значения props
и при последующих обновлениях useEffect
не выполнит код внутри блока if (init.current)
.
useRef возвращает изменяемый объект ref, свойство .current которого инициализируется переданным аргументом (initialValue). Возвращенный объект будет сохраняться в течение всего времени жизни компонента
Примечание. UseRef не уведомляет вас об изменении своего содержимого. Отключение свойства .current не вызывает повторного рендеринга.
Я использую
setTimeout
для обновления состояния
sessionTimeout
через каждую 1 секунду, чтобы обновить таймер, поэтому обновление состояния будет выполнять ловушку
useEffect
после каждого обновления, поскольку
sessionTimeout
входит в
useEffect
зависимость.
Попробуйте это.
import React, { useEffect, useState, useRef } from "react";
import DialogBox from "./DialogBox";
import Logout from "./Logout";
export default function Child({ warningTime, timeout }) {
const [showDialog, setShowDialog] = useState(false);
const [showLogout, setShowLogout] = useState(false);
const [sessionTimeout, setSessionTimeout] = useState(timeout);
const init = useRef(true);
const progressbar = useRef(warningTime);
useEffect(() => {
if (init.current) {
init.current = false;
let sessionTime = localStorage.getItem("timeout");
if (sessionTime && sessionTime < warningTime) {
progressbar.current = sessionTime;
} else {
progressbar.current = warningTime;
}
if (sessionTime) {
setSessionTimeout(prevState => sessionTime);
} else {
localStorage.setItem("timeout", sessionTimeout);
}
}
let sessionTimeoutInterval = null;
if (sessionTimeout > 0) {
sessionTimeoutInterval = setTimeout(() => {
if (sessionTimeout <= warningTime) {
openDialog();
}
setSessionTimeout(sessionTimeout => {
let updatedtime = sessionTimeout - 1;
localStorage.setItem("timeout", updatedtime);
return updatedtime;
});
}, 1000);
} else {
localStorage.removeItem("timeout");
handleDialogClose();
handleLogout();
clearTimeout(sessionTimeoutInterval);
}
return () => {
if (sessionTimeoutInterval) clearTimeout(sessionTimeoutInterval);
};
}, [sessionTimeout]);
function openDialog() {
setShowDialog(true);
}
function handleDialogClose() {
setShowDialog(false);
}
function handleLogout() {
setShowLogout(true);
}
function addMoreTimeHandler() {
handleDialogClose();
setSessionTimeout(sessionTimeout => {
localStorage.setItem("timeout", timeout);
return timeout;
});
}
return (
<div>
{showLogout ? <Logout /> : "Time remaning: " + sessionTimeout}
{showDialog ? (
<DialogBox
progressBar={progressbar.current - 1}
sessionTimeout={sessionTimeout}
addMoreTime={addMoreTimeHandler}
/>
) : null}
</div>
);
}
Живой пример