首页 > 解决方案 > 更新路由器中的状态变量

问题描述

我目前正在开发一个 React 站点,并且我有一个自定义HeaderBar组件,我想在其上显示当前页面标题。我计划只从路由器更新一个状态变量来更改标题。但是,可以理解的是,这会导致“重新渲染过多”错误。

这是我当前的代码:

function App() {
  const [pageTitle, setPageTitle] = useState("")

  return (
    <div>
      <Router>
        <HeaderBar siteTitle="My Website Name" pageTitle={pageTitle} />

        <Switch>
          <Route path="/login">
            {setPageTitle("Login")}
            <h1>Login Page</h1>
          </Route>

          <Route path="/main">
            {setPageTitle("Main")}
            <h1>Main Page</h1>
          </Route>
          
          <Route path="/about">
            {setPageTitle("About")}
            <h1>About Page</h1>
          </Route>
        </Switch>
      </Router>
    </div>
  );
}

显然,我可以将HeaderBar声明移动到每条路线中,但这对我来说似乎是一个骇人听闻的解决方案。

有没有更好的方法来解决这个问题?

标签: reactjsreact-routeruse-state

解决方案


在 JSX 中调用函数时,这些函数会在每个渲染上执行,这将导致在每个渲染上setPageTitle执行 3 个调用(尽管在您的情况下,只会setPageTitle调用第一个,因此会导致更新过多在调用 first setPageTitle、更新状态、再次渲染和再次调用它之间循环)。

理想情况下,如果为每个路由定义组件,则需要setPageTitle在 return 语句之外调用(即在 JSX 之外,在渲染之前),这将导致setPageTitle只有在访问相应路由时才会调用。

为了在不为路由定义组件的情况下做到这一点,您可以执行以下操作:

function App() {
  const [pageTitle, setPageTitle] = useState("")

  return (
    <div>
      <Router>
        <HeaderBar siteTitle="My Website Name" pageTitle={pageTitle} />

        <Switch>
          <Route path="/login" render={() => {
            setPageTitle("Login");
            return (<h1>Login Page</h1>);
          }}>
          </Route>

          <Route path="/main" render={() => {
            setPageTitle("Main");
            return (<h1>Main Page</h1>);
          }}>
          </Route>
          
          <Route path="/about" render={() => {
            setPageTitle("About");
            return (<h1>About Page</h1>);
          }}>
          </Route>
        </Switch>
      </Router>
    </div>
  );
}

推荐阅读