首页 > 解决方案 > React Hooks (Functional) Lifecycle: 在 useEffect() 代码之前渲染的组件

问题描述

我正在使用 React 功能组件。我熟悉类生命周期,但不熟悉功能生命周期。我的问题是这个组件是在useEffect()..中执行的初始化完成之前渲染的。在我的检查中,状态变量是否为真。return()

  1. 我首先看到我的非错误布局(TopNav& Main
  2. 在 2-3 秒内。屏幕更改为Error布局

处理功能组件的顺序是什么?在评估错误条件之前,我无法呈现非错误布局。

function App() {

    const [error, setError] = useState({});
    const [userInfo, setUserInfo] = useState({});

    const fetchUserInfo = async () => {
       const url = 'http://myapp.com/fetchUserInfo';
       try {
          const response = await axios.get(url);
          setUserInfo(response.data);
       }
       catch (error) { 
          setError(error);
       }
    }  

    // On initialization, fetch UserInfo
    useEffect(() => {    
        fetchUserInfo();
    }, []);

    return (
        <div className="App">
            <Router>
                <Header />
                
                {error.message
                    ? 
                        <Error error={error} /> 
                    :
                        <div>
                            <TopNav userInfo={userInfo} />
                            <Main userInfo={userInfo} />
                        </div>
                }
                
                <Footer />
            </Router>
        </div>
  );
}

标签: reactjs

解决方案


useEffect回调函数在渲染周期后被调用,所以一旦你的渲染完成,你的fetchUserInfo调用就会被调用,这又是一个异步操作。

相反,您应该拥有一个加载状态,让 UI 等待 API 提供的响应以显示适当的 UI

function App() {
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState({});
    const [userInfo, setUserInfo] = useState({});

    const fetchUserInfo = async () => {
       const url = 'http://myapp.com/fetchUserInfo';
       setIsLoading(true);
       try {
          const response = await axios.get(url);
          setUserInfo(response.data);
       }
       catch (error) { 
          setError(error);
       }
       finally {
           setIsLoading(false);
       }
    }  

    // On initialization, fetch UserInfo
    useEffect(() => {    
        fetchUserInfo();
    }, []);

    return (
        <div className="App">
            <Router>
                <Header />
                
                {isLoading? <Loader />: error.message
                    ? 
                        <Error error={error} /> 
                    :
                        <div>
                            <TopNav userInfo={userInfo} />
                            <Main userInfo={userInfo} />
                        </div>
                }
                
                <Footer />
            </Router>
        </div>
  );
}

推荐阅读