React 中带有 useEffect 的异步上下文

Posted

技术标签:

【中文标题】React 中带有 useEffect 的异步上下文【英文标题】:asynchronous context with useEffect in React 【发布时间】:2020-05-29 06:28:50 【问题描述】:

我正在尝试使用从上下文组件接收的标头值创建一个 api 请求。然而,一旦页面组件被加载,它就会抛出一个Cannot read property '_id' of null 异常。有没有办法在加载上下文后立即运行 useEffect 函数?

主要组件:

import React,  useState, useEffect, useContext  from "react";
import "./overview.scss";

/* COMPONENTS */;
import axios from 'axios';
import  GlobalContext  from '../../components/context/global';

const Overview = () => 
  const [bookings, setBookings] = useState([]);
  const [loaded, setLoaded] = useState(false);

  const [user, setUser] = useContext(GlobalContext);

  useEffect(() => 
      axios
      .get(`/api/v1/bookings/user/$user._id`)
      .then(res => setBookings(res.data))
      .catch(err => console.log(err))
      .finally(() => setLoaded(true));
  , [user]);

上下文组件:

import React, useState, useEffect, createContext from 'react';
import jwt from 'jsonwebtoken';

/* GLOBAL VARIABLES (CLIENT) */
export const GlobalContext = createContext();

export const GlobalProvider = props => 

    /* ENVIRONMENT API URL */
    const [user, setUser] = useState([]);

    useEffect(() => 
        const getSession = async () => 
            const user = await sessionStorage.getItem('authorization');
            setUser(jwt.decode(user));
    
    getSession();
    , [])

    return (
        <GlobalContext.Provider value=[user, setUser]>
            props.children
        </GlobalContext.Provider>
    );
;

【问题讨论】:

【参考方案1】:

这里的问题是useEffect 正在挂载上运行,而您还没有用户。你只需要防范这种情况

useEffect(() => 
  if (!user) return;

  // use user._id
,[user])

自然,当 Context 获取用户时,它应该强制重新渲染您的组件,并且随着依赖项发生变化,useEffect 自然应该重新运行。

【讨论】:

【参考方案2】:

在渲染你 GlobalProvider 之前放一个条件,例如:

 return (
    user.length&&<GlobalContext.Provider value=[user, setUser]>
        props.children
    </GlobalContext.Provider>
);

如果用户不是数组,就使用这个

 return (
    user&&<GlobalContext.Provider value=[user, setUser]>
        props.children
    </GlobalContext.Provider>
);

【讨论】:

感谢您的回复,但不幸的是它给了我一个Cannot read property length of null。我想异步函数还没有加载。 为什么是user.length?看起来 user 不会是这里的数组 const [user, setUser] = useState([]); ? @FrançoisRichard 啊,我明白了,状态的默认值具有误导性,因为它没有被用作数组(语言的使用也不会暗示它,都是单数)。此外,FWIW,您不希望在上下文中使 user 成为 useEffect 的依赖项,否则您最终会出现获取用户数据的连续循环。 是的,关于循环

以上是关于React 中带有 useEffect 的异步上下文的主要内容,如果未能解决你的问题,请参考以下文章

React - 带有异步 setState 的 useEffect 导致额外的重新渲染

React UseEffect 依赖于上下文不会立即更新组件

如何在 React 的 UseEffect() 中调用异步函数?

React TypeScript 16.8 如何使 useEffect() 异步

[react] useEffect和useLayoutEffect有什么区别?

React:在 useEffect 中调用上下文函数时防止无限循环