繁体   English   中英

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

[英]React/React Context API: Wait for context values when using useEffect() hook

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

  1. 在最高阶组件中,检查用户是否已登录,如果已登录,则更新 'userinfo' 上下文值。
  2. 在 Profile.js 中,获取 'userinfo' 上下文值。
  3. 检查'userinfo'是否为null,并相应调用不同的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;

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

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) */
   );
}

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

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

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

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

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>
);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM