导航到该组件后反应功能组件渲染两次,但是在尝试刷新时,仅渲染一次

Posted

技术标签:

【中文标题】导航到该组件后反应功能组件渲染两次,但是在尝试刷新时,仅渲染一次【英文标题】:React Functional Component Render twice after navigate to that Component, But when trying to refresh, Rendered only once 【发布时间】:2021-10-11 14:49:48 【问题描述】:

当我使用 react-router 访问一个功能组件时,它会渲染两次。 但是,当我刷新该组件的页面时,它只会呈现一次。

为了测试,创建了这样的空功能组件:

import React from 'react'

const TestFunctional: React.FC<any> = () => 
  console.log('Test===>>>') // console log twice when navigate to this component
  return <></>


export default TestFunctional

这是App.tsx中的路由器

import React from 'react'
import  Route, Switch, useLocation, withRouter  from 'react-router-dom'
import TestFunctional from 'views/Test'

const AnimatedSwitch = withRouter(( location ) => (    
  <Switch>
     <Route exact path="/" component=StartPage />
     <Route exact path="/test" component=TestFunctional />
  </Switch>
))

const App = () => 
  return (
    <div className="app">
      <Web3ReactManager>
        <AnimatedSwitch />
      </Web3ReactManager>
    </div>
  )


export default App

我没有在index.tsx 中使用React.StrictMode

ReactDOM.render(
  <ApolloProvider client=client>
    <Provider store=store>
      <ConnectedRouter history=history>
        <Web3ReactProvider getLibrary=getLibrary>
          <Web3ProviderNetwork getLibrary=getLibrary>
            <App />
          </Web3ProviderNetwork>
        </Web3ReactProvider>
      </ConnectedRouter>
    </Provider>
  </ApolloProvider>,
  document.getElementById('root')
)

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers
serviceWorker.unregister()

所以这有点奇怪。 当我刷新此页面时,console.log('Test===&gt;&gt;&gt;') 只显示一次。 什么是错误以及如何解决双重渲染问题?

【问题讨论】:

【参考方案1】:

为什么会有这样的问题?您应该设计/编写您的组件,假设它可以随时重新渲染。 React 甚至在 a new rendering mode 上工作,您的组件可能会在它实际“在 DOM 中渲染”之前被渲染多次。

至于为什么它实际上会渲染两次?不确定,可能只是快速的 ReactDOM。作为旁注,documentation for component 确实对Route 有此警告:

当你使用组件(而不是renderchildren,下面) 路由器使用React.createElement 从 给定的组件。这意味着如果您向 组件道具,您将在每次渲染时创建一个新组件。这 导致现有组件卸载和新组件 安装而不是仅仅更新现有组件。使用时 用于内联渲染的内联函数,使用 renderchildren 道具(下)。

虽然这不应该适用于这种情况,但仍然很容易知道。

【讨论】:

感谢您的提示。我的问题中有趣的一点是 Refreshing && Direct Open(Url Copy and open to new tab) 只渲染一次。当我来自另一个页面时,只有两次。 我想这与 ReactDOM 设置其内部状态有关,然后可能是另一个状态更改以响应使用 pushState 更改浏览器的 URL。如果将 component=TestFunctional 替换为 render=() =&gt; &lt;TestFunctional /&gt;,React 可能通过不重新渲染 TestFunctional 来优化它,因为它的状态/道具永远不会改变。 还是和&lt;Route exact path="/test" render=() =&gt; &lt;TestFunctional /&gt; /&gt;一样 那就不知道了,只能怪 ReactDOM 内部了。在他们的辩护中,组件在大多数情况下应该是“抗重新渲染”的,特别是当你将它用于这些属性被注入组件的目的时,即location

以上是关于导航到该组件后反应功能组件渲染两次,但是在尝试刷新时,仅渲染一次的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的反应组件在初始加载时渲染两次?

构造函数和渲染方法在反应组件中运行两次

反应屏幕之间的本机导航

反应路由器不渲染组件

等待反应上下文后组件不重新渲染

反应父组件不重新渲染