React Hooks 有条件地渲染登录/注销 w/本地存储变量

Posted

技术标签:

【中文标题】React Hooks 有条件地渲染登录/注销 w/本地存储变量【英文标题】:React Hooks Conditionally Render Login/Logout w/ Local Storage Variable 【发布时间】:2020-04-13 06:22:59 【问题描述】:

我希望导航栏根据本地存储中是否存储令牌有条件地显示“登录”或“注销”。我让它有点工作,但有时会有延迟,比如我在注销时清除了令牌,但导航栏在我刷新页面之前不会更新。我尝试添加一个存储布尔值的上下文变量来跟踪 loginStatus。我不确定这是否是最好的方法?我仍然看到该组件有时在我刷新页面之前不会更新。

export default function Nav() 
    const  loginStatus  = useContext(AuthContext)

    const navOptions = useLoginStatus()
    //useEffect(() => , [loginStatus]) ?? can I do this to force the nav component to update when the loginStatus context variable changes?

    return (
        <nav className="Nav">
            <Link to="/">
                <span className="logo">
                    ' '
                    AskifyLogo
                </span>
            </Link>
            <div className="profile-tools">
                navOptions
            </div>
        </nav>
    )


function useLoginStatus() 
    const  updateLoginStatus  = useContext(AuthContext)

    const handleLogoutClick = () => 
        updateLoginStatus(false)
        TokenService.clearAuthToken()
    

    const renderLogoutLink = () => (
            <div className='Nav__logged-in'>
                <Link
                    onClick=handleLogoutClick
                    to='/'>
                        Logout
                </Link>
            </div>
    );

    const renderLoginLink = () => (
            <div className='Nav__not-logged-in'>
                <Link to='/register'>
                    Register
                </Link>
                <Hyph />
                <Link to="/login">
                    Log in
                </Link>
            </div>
    );

    return TokenService.hasAuthToken() ? renderLogoutLink() : renderLoginLink()

【问题讨论】:

【参考方案1】:

当有 API 调用(且令牌已过期)或用户未与页面交互且令牌已过期时,您希望更新导航栏。要检测最新的,您可以在收到令牌后使用 setTimeout。此外,您可以使用令牌存储过期时间,并在刷新页面时从保存的时间重置超时。

另一种选择是使用中间件,例如this

【讨论】:

【参考方案2】:

Hooks 函数不能返回 jsx 元素!如果你返回一个 JSX 元素,你的函数会自动转换成一个组件,而不是一个自定义的钩子函数。 所以你应该更新你的钩子:

function useLoginStatus() 
    const  updateLoginStatus  = useContext(AuthContext)

    const handleLogoutClick = () => 
        updateLoginStatus(false)
        TokenService.clearAuthToken()
    

    const renderLogoutLink = () => (
            <div className='Nav__logged-in'>
                <Link
                    onClick=handleLogoutClick
                    to='/'>
                        Logout
                </Link>
            </div>
    );

    const renderLoginLink = () => (
            <div className='Nav__not-logged-in'>
                <Link to='/register'>
                    Register
                </Link>
                <Hyph />
                <Link to="/login">
                    Log in
                </Link>
            </div>
    );

    return 
     isLoggedIn: TokenService.hasAuthToken(),
     loggedInRender: renderLoginLink,
     loggedOutRender: 
    ;

现在,您可以将此函数用作 react 自定义钩子函数。 在您的组件中实现:

export default function Nav() 
    const  loginStatus  = useContext(AuthContext)

    const isLoggedIn, loggedInRender, LoggedOutRender = useLoginStatus()
    //useEffect(() => , [loginStatus]) ?? can I do this to force the nav component to update when the loginStatus context variable changes?

    return (
        <nav className="Nav">
            <Link to="/">
                <span className="logo">
                    ' '
                    AskifyLogo
                </span>
            </Link>
            <div className="profile-tools">
                isLoggedIn ? loggedInRender() : LoggedOutRender()
            </div>
        </nav>
    )

【讨论】:

伟大的推荐!谢谢!

以上是关于React Hooks 有条件地渲染登录/注销 w/本地存储变量的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React Hooks 在地图函数内动态和有条件地呈现选择选项

在 React 中使用登录和注销的用户渲染组件

React(五)深入React-Hooks工作机制,原理

React - 有条件地渲染多个元素

React Native Redux App 中的条件渲染失败

[react] 怎样有条件地渲染组件?