为什么 useEffect 在子组件渲染之前执行?

huangapple go评论68阅读模式
英文:

Why useEffect gets executed before child compenents rendered?

问题

我有意外的行为。我在App组件的顶部声明的“user”变量默认为null。

在第一次启动或刷新路径为/时,App组件的useEffect在子组件(即Login)之前执行。这种行为的原因是什么?

App.js

import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { useAuthContext } from './hooks/useAuthContext';
import { useEffect } from 'react';

// 页面和组件
import Home from './pages/Home';
import Login from './pages/Login';
import Signup from './pages/Signup';
import Navbar from './components/Navbar';

function App() {
  const { user } = useAuthContext();

  useEffect(() => {
    console.log("App useffect");
  }, []);

  return (
    <div className="App">
      <BrowserRouter>
        <Navbar />
        <div className="pages">
          {console.log("Route main")}
          <Routes>
            <Route 
              path="/"
              element={user ? <Home /> : <Navigate to="/login" />}
            />
            <Route 
              path="/login" 
              element={!user ? <Login /> : <Navigate to="/" />}
            />
            <Route 
              path="/signup" 
              element={!user ? <Signup /> : <Navigate to="/" />}
            />
          </Routes>
        </div>
      </BrowserRouter>
    </div>
  );
}

export default App;

Login.js

import { useEffect } from 'react';

const Login = () => {

  console.log('Login here:');

  useEffect(() => {
    console.log("Login here: useEffect");
  }, []);

  return (
    <div>Login</div>
  );
}

export default Login;

请注意,这只是代码的翻译部分。如果您有其他问题或需要更多帮助,请随时提出。

英文:

i have unexpected behaviour. "user" variable that i declared at the top of App compenent is null by default.

At the first start or refresh of path=/, useEffect of App compenent gets executed before child compenent which is Login, What is the reason of this behaviour ?

App.js

import { BrowserRouter, Routes, Route, Navigate } from &#39;react-router-dom&#39;
import { useAuthContext } from &#39;./hooks/useAuthContext&#39;
import { useEffect }from &#39;react&#39;
// pages &amp; components
import Home from &#39;./pages/Home&#39;
import Login from &#39;./pages/Login&#39;
import Signup from &#39;./pages/Signup&#39;
import Navbar from &#39;./components/Navbar&#39;
function App() {
const { user } = useAuthContext()
useEffect(() =&gt; {
console.log(&quot;App useffect&quot;)
}, [])
return (
&lt;div className=&quot;App&quot;&gt;
&lt;BrowserRouter&gt;
&lt;Navbar /&gt;
&lt;div className=&quot;pages&quot;&gt;
{console.log(&quot;Route main&quot;)}
&lt;Routes&gt;
&lt;Route 
path=&quot;/&quot;
element={user ? &lt;Home /&gt; : &lt;Navigate to=&quot;/login&quot; /&gt; } 
/&gt;
&lt;Route 
path=&quot;/login&quot; 
element={!user ? &lt;Login /&gt; : &lt;Navigate to=&quot;/&quot; /&gt;} 
/&gt;
&lt;Route 
path=&quot;/signup&quot; 
element={!user ? &lt;Signup /&gt; : &lt;Navigate to=&quot;/&quot; /&gt;} 
/&gt;
&lt;/Routes&gt;
&lt;/div&gt;
&lt;/BrowserRouter&gt;
&lt;/div&gt;
);
}
export default App;

Login.js

import { useEffect }from &#39;react&#39;
const Login = () =&gt; {
console.log(&#39;Login here:&#39;)
useEffect(() =&gt; {
console.log(&quot;Login here:&#39; useffect&quot;)
}, [])
return (
&lt;div&gt;Login&lt;/div&gt;
)
}
export default Login

答案1

得分: 0

Navigate 是一个 React 组件。根据文档: "一个 <Navigate> 元素在被渲染时改变了当前的位置。" 这意味着当你访问 / 路由时,你的 App.js 会被渲染,首先渲染了 Navigate 组件,然后触发了 App.js 中的 useEffect。之后 <Navigate> 组件将位置更改为 /login,然后由 react router 渲染了你的 Login.js,然后触发了 Login.js 中的 useEffect。

英文:

Navigate is a React component. According to documentation: "A &lt;Navigate&gt; element changes the current location when it is rendered.".

It means that your App.js is getting rendered and it renders the Navigate component first as you hit / route and then your App.js useEffect trigger. After &lt;Navigate&gt; component changes the location to /login- your Login.js is getting rendered by the react router and then useEffect in Login.js trigger.

答案2

得分: 0

Sure, here is the translated content:

这就是 &lt;Navigate /&gt; 的简单外观,

function Navigate() {
  React.useEffect(
    () =&gt; navigate(JSON.parse(jsonPath), { replace, state, relative }),
    [navigate, jsonPath, relative, replace, state]
  );

  return null;
}

它还使用了 useEffect 来处理副作用(替换 URL ),而 &lt;Navigate /&gt; 的渲染阶段只返回 null

所以它按预期工作。它首先渲染您的应用程序,然后渲染您的 &lt;Navigate /&gt;,它返回 null。渲染完成,然后执行副作用。然后,在所有这些之后,&lt;Navigate /&gt; 中的副作用是导致渲染 &lt;Login /&gt; 页面的原因。

英文:

This is what &lt;Navigate /&gt; simply looks like,

function Navigate() {
React.useEffect(
() =&gt; navigate(JSON.parse(jsonPath), { replace, state, relative }),
[navigate, jsonPath, relative, replace, state]
);
return null;
}

It also uses a useEffect to handle the side-effect ( replace the url ) and the render phase of the &lt;Navigate /&gt; returns just null.

So it works as expected. It renders your App, then It renders your &lt;Navigate /&gt; which returns null. Rendering completed and then it executed the side effects. Then after all of that, the side effect in the &lt;Navigate /&gt; is the one which causes to render &lt;Login /&gt; page.

huangapple
  • 本文由 发表于 2023年5月25日 20:32:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332305.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定