首页 > 解决方案 > React 路由器导致无效的钩子调用

问题描述

我有一个使用react-router. 我的路由的简约版本如下:

<Router>
   <div className="App">
      <Sidebar />
      <div className="app-container">
        <Switch>
          <Route path="/" exact render={Home} />
          <Route path="/logs" exact render={Logs} />
          <Route path="/log/:logID" exact render={Log} />
        </Switch>
      </div>
   </div>
</Router>

但是,每当我访问包含 React 挂钩的路由时,我的应用程序就会崩溃并出现以下错误:

Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://.../react-invalid-hook-call for tips about how to debug and fix this problem.

我可以通过render={() => <Log />}Route组件中输入类似的功能来绕过它,但是这样做会使我无法访问match.params组件。是否有一个修复程序可以让我在render={Log}不引发错误的情况下使用?

编辑:

下面是一个Home会使应用程序崩溃的组件示例:

import React, { useState } from 'react'

export default function Home() {

    const [foo, setFoo] = useState('bar');

    return (
        <div>
            Home
        </div>
    )
}

调用时会抛出错误useState。对于任何其他反应钩子,都会观察到相同的行为。

标签: javascriptreactjsreact-router

解决方案


来自 react-router 文档:

当你使用组件(而不是渲染或子,下面)时,路由器使用 React.createElement 从给定组件创建一个新的 React 元素。这意味着如果您为组件属性提供内联函数,您将在每次渲染时创建一个新组件。这会导致现有组件卸载和新组件安装,而不是仅仅更新现有组件。使用内联函数进行内联渲染时,请使用 render 或 children 道具(如下)。

您真的不想在每次重新渲染父级时都安装路由组件。我建议将组件作为孩子传递 - https://reactrouter.com/web/api/Route


推荐阅读