使用React Router时,使用useEffect执行的顺序混乱。

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

using useeffect with react router execute out of order

问题

The useEffect代码 in my route runs before my useEffect code in app.js because useEffect in React runs after the initial render of a component. In your case, the Home component (defined in Home.js) is rendered inside the RouterProvider in App.js, and its useEffect is called during that render.

This behavior is expected in React and is not something you need to prevent, as it follows the order of component rendering. If you want specific code in App.js's useEffect to run before code in Home.js's useEffect, you can place it outside the useEffect in App.js.

If you have specific synchronization or dependency requirements between these useEffect calls, you can handle them by passing dependencies or using Redux actions and reducers to manage the state in a more controlled manner.

英文:

I was trying to use useEffect in my app.js and setting some data to my redux and using that data in my route page(inside useEffect) resulting me finding this strange behavior unless it is how should be and i am in the wrong D:.
This is a simplified code to show my problem.

In the Code, I have four console.log() and the order in the browser developer console is as follows:

App.js    :7 App
Home.js   :4 Home
Home.js   :6 homeUseEffect
App.js    :9 appUseEffect

the log outside of useEffect runs as normal but inside useEffect the route runs before the app.js which the route is declared in.

app.js

import React, { useEffect } from 'react';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import Home from './pages/Home';
const router = createBrowserRouter([{ path: '/', element: <Home /> }]);
const App = () => {
  console.log('App');
  useEffect(() => {
    console.log('appUseEffect');
  }, []);

  return <RouterProvider router={router}></RouterProvider>;
};

export default App;

home.js

import React, { useEffect } from 'react';
const Home = () => {
  console.log('Home');
  useEffect(() => {
    console.log('homeUseEffect');
  }, []);
  return <div>Home</div>;
};
export default Home;

why the useEffect code in my route runs before my useEffect code in app.js
is it how it should be?
and how can I prevent that?

答案1

得分: 2

这个行为按预期工作。

/**
 * ------------------ 组合组件的生命周期 ------------------
 *
 * - constructor: 初始化状态。实例现在被保留。
 *   - componentWillMount
 *   - render
 *   - [子组件的构造函数]
 *     - [子组件的componentWillMount和render]
 *     - [子组件的componentDidMount]
 *     - componentDidMount
 *
 *       更新阶段:
 *       - componentWillReceiveProps(只有在父组件更新时才调用)
 *       - shouldComponentUpdate
 *         - componentWillUpdate
 *           - render
 *           - [子组件的构造函数或接收props阶段]
 *         - componentDidUpdate
 *
 *     - componentWillUnmount
 *     - [子组件被销毁]
 * - (已销毁): 实例现在为空,由React释放并准备垃圾回收。
 *
 * -------------------------------------------------------
 */

componentDidMount 文档中:

子组件的 componentDidMount() 方法在父组件之前调用。

我们还知道 useEffect(() => []) 等同于 componentDidMount() 生命周期方法。

在类组件中定义 componentDidMountcomponentDidUpdatecomponentWillUnmount 在功能上等同于在函数组件中调用 useEffect

这就是为什么你会得到以下日志:

App
Home
homeUseEffect
appUseEffect

函数组件执行发生在 "渲染阶段",由 useEffect() 钩子或 componentDidMount() 方法声明的效果将在 "提交阶段" 执行。

请参考下面的图表:

使用React Router时,使用useEffect执行的顺序混乱。

英文:

This behavior works as expected.

/**
 * ------------------ The Life-Cycle of a Composite Component ------------------
 *
 * - constructor: Initialization of state. The instance is now retained.
 *   - componentWillMount
 *   - render
 *   - [children's constructors]
 *     - [children's componentWillMount and render]
 *     - [children's componentDidMount]
 *     - componentDidMount
 *
 *       Update Phases:
 *       - componentWillReceiveProps (only called if parent updated)
 *       - shouldComponentUpdate
 *         - componentWillUpdate
 *           - render
 *           - [children's constructors or receive props phases]
 *         - componentDidUpdate
 *
 *     - componentWillUnmount
 *     - [children's componentWillUnmount]
 *   - [children destroyed]
 * - (destroyed): The instance is now blank, released by React and ready for GC.
 *
 * -----------------------------------------------------------------------------
 */

From componentDidMount doc:

> The componentDidMount() method of child components is invoked before that of parent components.

We also know useEffect(() => []) is equivalent to componentDidMount() lifecycle method.

> defining componentDidMount, componentDidUpdate, and componentWillUnmount together in class components is equivalent to calling useEffect in function components

That's why you get the logs:

App
Home
homeUseEffect
appUseEffect

The function component execution happens in the "render phrase", the effect declared by the useEffect() hook or componentDidMount() method will be executed in the "commit phrase".

See the below diagram:

使用React Router时,使用useEffect执行的顺序混乱。

huangapple
  • 本文由 发表于 2023年5月10日 19:29:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/76217863.html
匿名

发表评论

匿名网友

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

确定