我有一个虚拟的工作公告板Web应用程序,使用react 和喜悦的用户界面的前端和用户界面.我使用喜悦UISnackbar 组件在用户执行某些操作(注册、登录等)后临时弹出一条消息.在快餐栏上,我将autoHideDurationprops 设置为{3000},这样它应该在3秒后消失.如果用户点击关闭图标或Snackbar之外的某个地方,Snackbar也会消失.

但是,如果用户在Snackbar出现后快速导航到其他页面,然后按下浏览器中的"返回"按钮,则Snackbar会重新出现,并且只有在初始计时器到期后才会消失.此外,看起来计时器不包括用户在其他页面上花费的时间,因此即使用户在其他页面上停留超过3秒,Snackbar也可以在导航回原始页面后重新出现.

这是一种不希望出现的行为,我希望当用户离开最初呈现Snackbar的页面时,Snackbar永远消失.

我的自定义SnackBarAlert组件如下:

import { useState, useEffect, useContext } from "react";
import { AuthContext } from "../store/AuthContext";
import { ProfileContext } from "../store/ProfileContext";
import { FeedbackContext } from "../store/FeedbackContext";
import { SnackBarAlert } from "./SnackBarAlert";
import { Container } from "@mui/joy";

export const SnackBarContainer = () => {

    const { authStatus, changeAuthStatus } = useContext(AuthContext);
    const { profile, changeProfile } = useContext(ProfileContext);
    const { feedback, changeFeedback } = useContext(FeedbackContext);
    
    const [loggedInAlert, setLoggedInAlert] = useState(false);
    const [loggedOutAlert, setLoggedOutAlert] = useState(false);
    const [registeredAlert, setRegisteredAlert] = useState(false);
    const [editedProfileAlert, setEditedProfileAlert] = useState(false);
    const [appliedAlert, setAppliedAlert] = useState(false);
    const [postedVacancyAlert, setPosterVacancyAlert] = useState(false);
    const [editedVacancyAlert, setEditedVacancyAlert] = useState(false);
    const [deletedVacancyAlert, setDeletedVacancyAlert] = useState(false);
    const [postedFeedbackAlert, setPostedFeedbackAlert] = useState(false);
    
    useEffect(() => {
        authStatus.justLoggedOut && setLoggedOutAlert(true);
        authStatus.justLoggedIn && setLoggedInAlert(true);
        profile.justRegistered && setRegisteredAlert(true);
        profile.justEditedProfile && setEditedProfileAlert(true);
        profile.justApplied && setAppliedAlert(true);
        profile.justPostedVacancy && setPosterVacancyAlert(true);
        profile.justEditedVacancy && setEditedVacancyAlert(true);
        profile.justDeletedVacancy && setDeletedVacancyAlert(true);
        feedback && setPostedFeedbackAlert(true);
    }, []);
    
    return (
        <Container>
            <SnackBarAlert
                open={loggedInAlert}
                text="You successfully logged in!"
                onClose={() => {
                    setLoggedInAlert(false);
                    changeAuthStatus({
                        ...authStatus,
                        justLoggedIn: null
                    });
                }}
            />
            <SnackBarAlert
                open={loggedOutAlert}
                text="You logged out!"
                onClose={() => {
                    setLoggedOutAlert(false);
                    changeAuthStatus({
                        ...authStatus,
                        justLoggedOut: null
                    });
                }}
            />
            <SnackBarAlert
                open={registeredAlert}
                text="You succesfully registered! Now, please log in to your account."
                onClose={() => {
                    setRegisteredAlert(false);
                    changeProfile({
                        ...profile,
                        justRegistered: null
                    });
                }}
            />
            <SnackBarAlert
                open={editedProfileAlert}
                text="You successfully edited your profile!"
                onClose={() => {
                    setEditedProfileAlert(false);
                    changeProfile({
                        ...profile,
                        justEditedProfile: null
                    });
                }}
            />
            <SnackBarAlert
                open={appliedAlert}
                text="You succesfully applied for a vacancy"
                onClose={() => {
                    setAppliedAlert(false);
                    changeProfile({
                        ...profile,
                        justApplied: null
                    });
                }}
            />
            <SnackBarAlert
                open={postedVacancyAlert}
                text="You successfully posted a vacancy!"
                onClose={() => {
                    setPosterVacancyAlert(false);
                    changeProfile({
                        ...profile,
                        justPostedVacancy: null
                    });
                }}
            />
            <SnackBarAlert
                open={editedVacancyAlert}
                text="You successfully edited a vacancy!"
                onClose={() => {
                    setEditedVacancyAlert(false);
                    changeProfile({
                        ...profile,
                        justEditedVacancy: null
                    });
                }}
            />
            <SnackBarAlert
                open={deletedVacancyAlert}
                text="You deleted a vacancy!"
                onClose={() => {
                    setDeletedVacancyAlert(false);
                    changeProfile({
                        ...profile,
                        justDeletedVacancy: null
                    });
                }}
            />
            <SnackBarAlert
                open={postedFeedbackAlert}
                text="You successfully sent a message!"
                onClose={() => {
                    setPostedFeedbackAlert(false);
                    changeFeedback(null);
                }}
            />
        </Container>
    );

};

我的合并不同alert 的SnackBarContainer如下:

import { useState, useEffect, useContext } from "react";
import { AuthContext } from "../store/AuthContext";
import { ProfileContext } from "../store/ProfileContext";
import { FeedbackContext } from "../store/FeedbackContext";
import { SnackBarAlert } from "./SnackBarAlert";
import { Container } from "@mui/joy";

export const SnackBarContainer = () => {

    const { authStatus, changeAuthStatus } = useContext(AuthContext);
    const { profile, changeProfile } = useContext(ProfileContext);
    const { feedback, changeFeedback } = useContext(FeedbackContext);
    
    const [loggedInAlert, setLoggedInAlert] = useState(false);
    const [loggedOutAlert, setLoggedOutAlert] = useState(false);
    const [registeredAlert, setRegisteredAlert] = useState(false);
    const [editedProfileAlert, setEditedProfileAlert] = useState(false);
    const [appliedAlert, setAppliedAlert] = useState(false);
    const [postedVacancyAlert, setPosterVacancyAlert] = useState(false);
    const [editedVacancyAlert, setEditedVacancyAlert] = useState(false);
    const [deletedVacancyAlert, setDeletedVacancyAlert] = useState(false);
    const [postedFeedbackAlert, setPostedFeedbackAlert] = useState(false);
    
    useEffect(() => {
        authStatus.justLoggedOut && setLoggedOutAlert(true);
        authStatus.justLoggedIn && setLoggedInAlert(true);
        profile.justRegistered && setRegisteredAlert(true);
        profile.justEditedProfile && setEditedProfileAlert(true);
        profile.justApplied && setAppliedAlert(true);
        profile.justPostedVacancy && setPosterVacancyAlert(true);
        profile.justEditedVacancy && setEditedVacancyAlert(true);
        profile.justDeletedVacancy && setDeletedVacancyAlert(true);
        feedback && setPostedFeedbackAlert(true);
    }, []);
    
    return (
        <Container>
            <SnackBarAlert
                open={loggedInAlert}
                text="You successfully logged in!"
                onClose={() => {
                    setLoggedInAlert(false);
                    changeAuthStatus({
                        ...authStatus,
                        justLoggedIn: null
                    });
                }}
            />
            <SnackBarAlert
                open={loggedOutAlert}
                text="You logged out!"
                onClose={() => {
                    setLoggedOutAlert(false);
                    changeAuthStatus({
                        ...authStatus,
                        justLoggedOut: null
                    });
                }}
            />
            <SnackBarAlert
                open={registeredAlert}
                text="You succesfully registered! Now, please log in to your account."
                onClose={() => {
                    setRegisteredAlert(false);
                    changeProfile({
                        ...profile,
                        justRegistered: null
                    });
                }}
            />
            <SnackBarAlert
                open={editedProfileAlert}
                text="You successfully edited your profile!"
                onClose={() => {
                    setEditedProfileAlert(false);
                    changeProfile({
                        ...profile,
                        justEditedProfile: null
                    });
                }}
            />
            <SnackBarAlert
                open={appliedAlert}
                text="You succesfully applied for a vacancy"
                onClose={() => {
                    setAppliedAlert(false);
                    changeProfile({
                        ...profile,
                        justApplied: null
                    });
                }}
            />
            <SnackBarAlert
                open={postedVacancyAlert}
                text="You successfully posted a vacancy!"
                onClose={() => {
                    setPosterVacancyAlert(false);
                    changeProfile({
                        ...profile,
                        justPostedVacancy: null
                    });
                }}
            />
            <SnackBarAlert
                open={editedVacancyAlert}
                text="You successfully edited a vacancy!"
                onClose={() => {
                    setEditedVacancyAlert(false);
                    changeProfile({
                        ...profile,
                        justEditedVacancy: null
                    });
                }}
            />
            <SnackBarAlert
                open={deletedVacancyAlert}
                text="You deleted a vacancy!"
                onClose={() => {
                    setDeletedVacancyAlert(false);
                    changeProfile({
                        ...profile,
                        justDeletedVacancy: null
                    });
                }}
            />
            <SnackBarAlert
                open={postedFeedbackAlert}
                text="You successfully sent a message!"
                onClose={() => {
                    setPostedFeedbackAlert(false);
                    changeFeedback(null);
                }}
            />
        </Container>
    );

};

下面是我的登录页面组件的一个示例,它使用了Snackbar之一:

import { useContext, useEffect } from "react";
import { Link as RouterLink, useNavigate } from "react-router-dom";
import { Container, Typography, Card, CardContent, CardActions, Stack, Link } from "@mui/joy";
import { AuthContext } from "../store/AuthContext";
import { LoginForm } from "../components/LoginForm";
import { SnackBarContainer } from "../components/SnackBarContainer";

export const Login = () => {

    const navigate = useNavigate();
    const { authStatus } = useContext(AuthContext);
    
    useEffect(() => {
        authStatus.isLoggedIn && navigate("/");
    }, []);
    
    return (
        <Container>
            <Stack
                justifyContent="center"
                alignItems="center"
                spacing={5}
                sx={{ paddingY: { xs: 5, xl: 16 } }}
            >
                <Card variant="outlined" sx={{
                    width: { xs: "80%", sm: "60%", md: "40%" }
                }}>
                    <CardContent sx={{ alignItems: "center", textAlign: "center" }}>
                        <LoginForm />
                    </CardContent>
                    <CardActions>
                    </CardActions>
                </Card>
                <Typography>
                    <Link component={RouterLink} to="/candidate-register">
                        Register as a candidate here
                    </Link>
                </Typography>
                <Typography>
                    <Link component={RouterLink} to="/recruiter-register">
                        Register as a recruiter here
                    </Link>
                </Typography>
            </Stack>
            <SnackBarContainer />
        </Container >
    );
};

我的 idea 是,这个问题与我用来进行路由的Reaction路由如何处理Reaction应用程序中的状态有关,但我找不到解决它的方法.

任何帮助将不胜感激.

这款应用程序是实时的,可以here次访问.完整的代码可在GitHub here上获得.

推荐答案

我认为你可以通过几种方式来帮助解决这个问题.

  1. 它看起来像是在为消息干杯时呈现了单独的SnackBarContainer个组件.如果/当SnackBarContainer卸载时,使用useEffect清理功能设置快捷栏显示状态.

    export const SnackBarContainer = () => {
      const { authStatus, changeAuthStatus } = useContext(AuthContext);
      const { profile, changeProfile } = useContext(ProfileContext);
      const { feedback, changeFeedback } = useContext(FeedbackContext);
    
      const [loggedInAlert, setLoggedInAlert] = useState(false);
      const [loggedOutAlert, setLoggedOutAlert] = useState(false);
      const [registeredAlert, setRegisteredAlert] = useState(false);
      const [editedProfileAlert, setEditedProfileAlert] = useState(false);
      const [appliedAlert, setAppliedAlert] = useState(false);
      const [postedVacancyAlert, setPosterVacancyAlert] = useState(false);
      const [editedVacancyAlert, setEditedVacancyAlert] = useState(false);
      const [deletedVacancyAlert, setDeletedVacancyAlert] = useState(false);
      const [postedFeedbackAlert, setPostedFeedbackAlert] = useState(false);
    
      useEffect(() => {
        authStatus.justLoggedOut && setLoggedOutAlert(true);
        authStatus.justLoggedIn && setLoggedInAlert(true);
        profile.justRegistered && setRegisteredAlert(true);
        profile.justEditedProfile && setEditedProfileAlert(true);
        profile.justApplied && setAppliedAlert(true);
        profile.justPostedVacancy && setPosterVacancyAlert(true);
        profile.justEditedVacancy && setEditedVacancyAlert(true);
        profile.justDeletedVacancy && setDeletedVacancyAlert(true);
        feedback && setPostedFeedbackAlert(true);
    
        return () => {
          setLoggedOutAlert(false);
          setLoggedInAlert(false);
          setRegisteredAlert(false);
          setEditedProfileAlert(false);
          setAppliedAlert(false);
          setPosterVacancyAlert(false);
          setEditedVacancyAlert(false);
          setDeletedVacancyAlert(false);
          setPostedFeedbackAlert(false);
        };
      }, []);
    
      return (
        ...
      );
    };
    
  2. 使用更好地维护历史堆栈的导航操作.例如,假设Login组件在"/login"上呈现并成功验证,则当前代码将推送到"/".如果他们返回,他们会再次降落在"/login"号.使用REPLACE操作来帮助防止错误的返回导航操作,从而使用户无法返回到现在无效的页面.这个 idea 是为了防止用户导航回到最初启动toast的页面.

    示例:

    export const Login = () => {
      const navigate = useNavigate();
      const { authStatus } = useContext(AuthContext);
    
      useEffect(() => {
        // Redirect to "/" instead of pushing another history entry
        authStatus.isLoggedIn && navigate("/", { replace: true });
      }, []);
    
      ...
    };
    

Reactjs相关问答推荐

无法使用Apollo客户端GraphQL设置Next.js 14

使用下一步中的路由/导航不会立即加载路由

在数组对象内的数组上进行映射

自定义变量默认、聚焦和填充时所需TextField中标签的星号 colored颜色

MUI 日期 Select 器 - 最小日期混乱

Javascript - 正则表达式不适用于 MAC OS - 编码?

无法在 NextJS 中获取嵌套对象

面临 React 模式中点击外部条件的问题

使用获取的数据更新状态,但在try console.log 时它给出未定义

在 React-Select 中显示多值的倒序

cypress `cy.now()` Type 'Promise' 没有调用签名

如何在悬停时更改 MUI 卡内容

使用 react-markdown 组件时 Tailwind CSS 的问题

如何在不重新加载页面的情况下加载新添加的数据?

使用 axios 响应路由 Dom 操作

如何从 React Redux store 中删除特定项目?

axios post方法中的请求失败,状态码为500错误

ClearInterval 在 React 中的 useRef 没有按预期工作

Select MenuItem 时 Material-ui 不更改样式

如何在 NavBar 中设置动态标题