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

在useEffect更新的Context中无法访问user.token的问题咨询

问题:Context中useEffect更新user后,组件内useEffect调用的函数无法获取user.token

我给应用创建了一个Context,在ChatProvider的useEffect中从localStorage读取用户信息并更新user状态:

const ChatProvider = ({ children }) => {
    const [user, setuser] = useState({});
    const [selectedChat, setselectedChat] = useState();
    const [chats, setchats] = useState([]);
    const navigate = useNavigate();

    useEffect(() => {
        const userInfo = JSON.parse(localStorage.getItem('userInfo'));
        if (!userInfo) {
            navigate('/');
        } else {
            setuser(userInfo);
        }
    }, []);
    return (
        <ChatContext.Provider
            value={{ user, setuser, selectedChat, setselectedChat, setchats, chats }}
        >
            {children}
        </ChatContext.Provider>
    );
};
const ChatState = () => {
    return useContext(ChatContext);
};
export { ChatState };
export default ChatProvider;

随后在AllChats组件中访问user并发起请求:

const AllChats = () => {
    const { user, setselectedChat, selectedChat, setchats, chats } = ChatState();
    const toast = useToast();

    const fetchChats = expressAsyncHandler(async (req, res) => {
        try {
            const config = {
                headers: { Authorization: `Bearer ${user.token}` },
            };
            const { data } = await axios.get('/api/chat/allChats', config);
            console.log(data);
            setchats(data);
        } catch (error) {
            toast({
                title: 'Error occurred',
                description: 'Failed to load chats',
                status: 'error',
                duration: 5000,
                isClosable: true,
                position: 'top',
            });
        }
    });

    useEffect(() => {
        fetchChats();
    }, []);

    return <div>{user.token}</div>;
};

当前现象:页面上能正常渲染出user.token的值,但useEffect调用的fetchChats函数中无法获取到user.token(截图显示该值为undefined)。

问题截图

解决方案

原因

两个useEffect都在组件挂载阶段(空依赖数组)执行:

  • ChatProvider的useEffect会先读取localStorage再更新user状态,这个状态更新会触发AllChats重新渲染,但AllChats的useEffect已经提前执行了,此时它捕获的是初始的空user对象。
  • 页面能渲染出user.token是因为组件重新渲染后,return语句使用的是更新后的最新状态。

方案1:给AllChats的useEffect添加依赖项

修改AllChats中的useEffect,将user.token加入依赖数组,确保只有当user.token存在且变化时才发起请求,避免无效请求:

useEffect(() => {
    if (user.token) {
        fetchChats();
    }
}, [user.token]);

方案2:在fetchChats中直接读取localStorage

既然user状态来自localStorage,可跳过状态直接在请求时读取token,避免状态更新的时序问题:

const fetchChats = expressAsyncHandler(async () => {
    try {
        const userInfo = JSON.parse(localStorage.getItem('userInfo'));
        if (!userInfo?.token) return;
        
        const config = {
            headers: { Authorization: `Bearer ${userInfo.token}` },
        };
        const { data } = await axios.get('/api/chat/allChats', config);
        setchats(data);
    } catch (error) {
        toast({
            title: 'Error occurred',
            description: 'Failed to load chats',
            status: 'error',
            duration: 5000,
            isClosable: true,
            position: 'top',
        });
    }
});

方案3:在ChatProvider中提前初始化user状态

无需等到useEffect执行再设置user,直接在useState初始化时读取localStorage,这样组件挂载时就能拿到完整的用户状态:

const ChatProvider = ({ children }) => {
    // 初始化时直接从localStorage读取用户信息
    const [user, setuser] = useState(() => {
        const storedUser = localStorage.getItem('userInfo');
        return storedUser ? JSON.parse(storedUser) : {};
    });
    const [selectedChat, setselectedChat] = useState();
    const [chats, setchats] = useState([]);
    const navigate = useNavigate();

    useEffect(() => {
        const userInfo = JSON.parse(localStorage.getItem('userInfo'));
        if (!userInfo) {
            navigate('/');
        }
    }, []); // 此处仅处理未登录跳转逻辑

    return (
        <ChatContext.Provider
            value={{ user, setuser, selectedChat, setselectedChat, setchats, chats }}
        >
            {children}
        </ChatContext.Provider>
    );
};

这样AllChats挂载时就能获取到完整的user状态,空依赖的useEffect也能正常拿到user.token。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 12:04:54