簡體   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