React/React Context API:使用 useEffect() 钩子时等待上下文值

Posted

技术标签:

【中文标题】React/React Context API:使用 useEffect() 钩子时等待上下文值【英文标题】:React/React Context API: Wait for context values when using useEffect() hook 【发布时间】:2020-08-12 04:50:03 【问题描述】:

我正在使用 React 开发一个 Web 应用程序,这就是我想要做的:

    在最高阶组件中,检查用户是否已登录,如果已登录,则更新 'userinfo' 上下文值。 在 Profile.js 中,获取 'userinfo' 上下文值。 检查'userinfo'是否为空,并相应调用不同的API。

我写了下面的代码。问题在于,将 userinfo 上下文值传递给组件显然存在时间滞后。所以当使用 useEffect() hook 时,当 userinfo 不为 null 时 Profile.js 会渲染两次。

有没有办法修复此代码,使其等待“userinfo”变量,然后相应地调用相关 API,而不是之前?

下面是代码。有什么建议吗?提前非常感谢!

import React, useEffect, useContext from 'react';
import Userinfo from "../context/Userinfo";


function Profile(props) 

   const userinfo, setuserinfo=useContext(Userinfo);

   useEffect(()=>      
       ((userinfo==null)?
       /*API call A (When user is not logged in) */ :
       /*API call B (When user is logged in) */
       ),[userinfo])  

   return (
       (userinfo==null)?
       /*Elements to render when user is not logged in) */ :
       /*Elements to render when user is  logged in) */
   );


export default Profile;

【问题讨论】:

【参考方案1】:

这里最好的解决方案是在上下文提供程序中添加一个加载状态,一旦值更新,它就会重置。

function Profile(props) 

   const userinfo, loading, setuserinfo=useContext(Userinfo);

   useEffect(()=>      
       if(!loading) 
            ((userinfo==null)?
             /*API call A (When user is not logged in) */ :
            /*API call B (When user is logged in) */
            )
       
    ),[loading, userinfo])  

   if(loading) return <Loader />
   return (
       (userinfo==null)?
       /*Elements to render when user is not logged in) */ :
       /*Elements to render when user is  logged in) */
   );

【讨论】:

【参考方案2】:

我今天遇到了这个问题,我喜欢 Shubham 的做法。但是我解决它的方法只是从前一个组件中获取userinfo 并将其传递给这个配置文件组件。

但是,请确保像这样渲染 Profile 组件,以便确保 userinfo 存在:

function ParentComponent()
 // do sth to get the userinfo here
return(
  <ParentComponent>
     userinfo? <Profile userinfo=userinfo /> : null       
 <ParentComponent/>
)

【讨论】:

【参考方案3】:

假设您正在设置如下上下文:

import React from 'react';
const AuthContext = React.createContext(
    userInfo: null,
    isLoggedIn: false,
    loading: true,
    setUser: () =>  
);

export default AuthContext;

您正在像这样设置您的全球供应商:

import React from 'react';
import  AuthContext  from './AuthContext'; // path to the context

export default class GlobalUserContext extends React.Component
    constructor(props)
        super(props);
        this.state = 
            userInfo: null,
            isLoggedIn: false,
            loading: true
            
    

    componentDidMount()
        ( async() => 
            const currentUser = await getUser(); // say you are trying to log user in
            if(currentUser)
                this.setState(
                    userinfo: currentUser,
                    isLoggedIn: true,
                    loading: false
                );  
            

         )();
    
    
    setUser = (user, check) => 
        this.setState(userInfo: user, isLoggedIn: check);
    ;
    
    render()
        return (
            <AuthContext.Provider 
            value=
                user: this.state.user,
                setUser: this.setUser,
                isLoggedIn: this.state.isLoggedIn,
                loading: this.state.loading
            >
            this.props.children 
            </AuthContext.Provider>
        );
    


然后在你的功能组件中使用useEffect,你可以这样做:

import React,  useContext, useEffect from 'react';
import AuthContext                     from '../../contexts/AuthContext'; // your content path

export const MyComponent = () => 
const userInfo, isLoggedIn, loading = useContext(AuthContext);
useEffect(() => 
// here you can now ask if the user data is still loading like so:
if(!loading)
// do something 
// UserInfo is available

, [userInfo, loading]);
return (
<View>
anything
</View>
);

【讨论】:

以上是关于React/React Context API:使用 useEffect() 钩子时等待上下文值的主要内容,如果未能解决你的问题,请参考以下文章

React - 是不是在 useEffect 中调用 API

如何在 React js 中以表格格式显示 API 响应?

[react] react有几种构建组件的方式?可以写出来吗?

relativeLayout.setBackground(ContextCompat.getDrawable(context, R.drawable.sample_drawable));正在使 API

React-redux: React.js 和 Redux 架构的结合

React-Native with Redux:API 对象出现在我的 console.log 中,但不在我的视图中