You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Hooks为何不能用于条件判断?附登录跳转代码修复方案

问题解答

一、为什么React Hooks不能用在if这类条件判断中?

React Hooks的核心机制依赖调用顺序的稳定性:React会在组件每次渲染时,按顺序记录每个Hook的调用,以此关联对应的状态和副作用。如果把Hook放在if、循环或者嵌套函数里,组件不同渲染周期的Hook调用顺序可能改变,React就无法正确匹配之前存储的状态,导致状态混乱、渲染异常。

所以React强制要求:所有Hook必须在组件的顶层作用域调用,不能被条件逻辑包裹。你的代码里把useNavigate放到了tologin函数里,又在Redux reducer的条件分支中调用这个函数,完全违反了Hook的调用规则,自然报错。

二、修改代码实现登录后跳转

你的核心问题是把导航逻辑放到了Redux的slice里——Redux reducer是纯函数,不能调用React Hooks,也不应该处理页面导航这种UI层的副作用。正确的做法是:Redux只负责更新登录状态,导航逻辑放在React组件中处理。

修改后的代码:

1. AccountSlice.tsx(仅处理状态更新)

const AccountSlice = createSlice({
    name: "Account",
    initialState: {
        ActiveAccount: [],
        Accounts: [
            {id: 1, email: "Member@mail.com", password: "password", isActive:false, roles: "Member"},
            {id: 2, email: "Manager@mail.com", password: "password", isActive:false, roles: "Manager"}
        ]
    },
    reducers: {
        LoginFunc : (state, action) => {
            const account = state.Accounts.find(account => account.email === action.payload.email && account.password === action.payload.password);
            if(account != null){
                console.log("logged in");
                // 清空并更新活跃账户
                state.ActiveAccount = [account];
            }
        },
        LogOut : (state) => {
            console.log("Logged Out");
            state.ActiveAccount = [];
        }
    }
});

export default AccountSlice.reducer;
export const { LoginFunc, LogOut} = AccountSlice.actions; 

2. Login组件(处理导航逻辑)

import { useState, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';
import { LoginFunc } from './AccountSlice';

const Login = () => {
    const [Email, setEmail] = useState("");
    const [Password, setPassword] = useState("");
    const dispatch = useDispatch();
    const navigate = useNavigate();
    // 从Redux获取当前活跃账户
    const activeAccount = useSelector(state => state.Account.ActiveAccount[0]);

    // 监听活跃账户变化,登录成功后跳转首页
    useEffect(() => {
        if(activeAccount){
            navigate('/Home');
        }
    }, [activeAccount, navigate]);

    const handleSubmit = e => {
        e.preventDefault();
        dispatch(LoginFunc({email: Email, password: Password}));
    };

    return(
        <>    
            <div className="Login">
                <div className='Login-form'>
                    <form onSubmit={handleSubmit}>
                        <div>
                            <label htmlFor="email">邮箱</label>
                            <input type="email" id="email" value={Email} onChange={e => setEmail(e.target.value)}/>
                        </div>
                        <div>
                            <label htmlFor="Password">密码</label>
                            <input type="password" id="Password" value={Password} onChange={e => setPassword(e.target.value)}/>
                        </div>
                        <br />
                        <button className='form-control' type="submit">登录</button>
                    </form>
                </div>
            </div>
        </>   
    );
};

export default Login;

关键修改点:

  • 移除了slice里的tologin函数,Reducer只做状态更新,保持纯函数特性。
  • Login组件改用useDispatch、useSelector和useNavigate这些Hook(均在组件顶层调用,符合Hook规则)。
  • 通过useEffect监听Redux中activeAccount的变化,一旦登录成功(存在活跃账户)就执行页面跳转。

内容的提问来源于stack exchange,提问作者FriedBrain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 06:52:44