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

Zustand useStore重渲染时参数undefined问题排查求助

问题描述

登录应用并更新Zustand store后,调用loggedIn(cu)触发页面重渲染,抛出错误Uncaught TypeError: a is undefined,错误指向useAuthStore(useShallow(a => (...)))中的a在重渲染时为undefined。

Store代码

import {create} from 'zustand'

import {ITRUserInfoDTO, LoginResponse} from "../itr-client";

export type UserContextValue = {
    credentials: LoginResponse | null,
    expiration: number | null,
    user: ITRUserInfoDTO | null
}

export interface AuthState extends UserContextValue {
    loggedIn: (ctx: UserContextValue) => void
    logout: () => void
}

export const LOGGED_OUT_USER_CONTEXT: UserContextValue = {
    credentials: null,
    expiration: null,
    user: null
}

export const useAuthStore = create<AuthState>(
    (set) => ({
        ...LOGGED_OUT_USER_CONTEXT,
        loggedIn: (ctx: UserContextValue) => set((state) => set({...ctx})),
        logout: () => set((state) => set({...LOGGED_OUT_USER_CONTEXT,}))
    }));

组件代码

export default function LoginPage() {
    const {user, loggedIn} = useAuthStore(useShallow(a => ({user: a.user, loggedIn: a.loggedIn})))
    const [searchParams, setSearchParams] = useSearchParams();
    const redirectLocation = searchParams.get('redirect');
    const navigate = useNavigate()

    const go = () => redirectLocation > 0 ? navigate(redirectLocation, {replace: true}) : navigate('/home', {replace: true});
    // useEffect(() => {
    //     if (user) {
    //         go()
    //     }
    // })

    const tryLogin = useCallback((loginDTO) => {
        const authApi = new AuthenticationApi();
        authApi.authenticate({loginDTO})
            .then(loginResult => {
                const configuration = new Configuration({accessToken: loginResult.token});
                const userInformationApi = new UserInformationApi(configuration);
                userInformationApi.getMe().then(me => {
                    const cu = {
                        credentials: loginResult,
                        expiration: new Date().getTime() + loginResult.expiresIn,
                        user: me,
                    }
                    // alert(JSON.stringify(cu))
                    loggedIn(cu)
                }).catch(e => {alert(`Error: ${JSON.stringify(e)}`); console.error(e)});
            })
            .catch(error => console.error('Error', error))
            .finally(() => console.log("Done logging in"))
    }, [loggedIn, user])
问题原因

你的store中loggedIn和logout方法存在逻辑错误:在Zustand的set回调函数里嵌套调用了set,这会打乱Zustand的状态更新流程。Zustand的set函数仅接受两种参数:直接的状态对象,或一个返回状态对象的回调(该回调参数为当前状态)。嵌套调用set会导致状态更新异常,最终引发组件重渲染时useShallow接收的store状态a变为undefined。

解决方案

1. 修复Store中的状态更新逻辑

移除set的嵌套调用,直接传入状态对象或返回新状态:

export const useAuthStore = create<AuthState>(
    (set) => ({
        ...LOGGED_OUT_USER_CONTEXT,
        loggedIn: (ctx: UserContextValue) => set({...ctx}),
        logout: () => set({...LOGGED_OUT_USER_CONTEXT})
    }));

2. 优化组件逻辑

  • 恢复登录成功后的页面跳转逻辑,并添加正确的依赖项:
useEffect(() => {
    if (user) {
        go()
    }
}, [user, go])
  • 移除tryLogin中多余的user依赖(函数内部未使用该变量):
const tryLogin = useCallback((loginDTO) => {
    // 原有登录逻辑
}, [loggedIn])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:28:28