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

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

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

【问题讨论】:

    标签: javascript reactjs react-context


    【解决方案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>
        );
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-05-24
          • 2021-03-11
          • 2018-09-30
          • 1970-01-01
          • 2020-09-15
          • 2020-09-19
          • 2021-01-10
          • 2020-03-07
          相关资源
          最近更新 更多