【问题标题】:React Router `history` and `location` mismatched after back button后退按钮后反应路由器“历史”和“位置”不匹配
【发布时间】:2020-04-22 11:07:56
【问题描述】:

在我的 React 应用程序中,从主页导航到子页面然后点击后退按钮后,React <Router> 显示其内部状态与从 history 传递的道具不匹配的位置以及不正确的 <Route>为地址栏中当前显示的 URL 显示

<Route> 的内容确实发生了变化;数据由位置更改 Redux 操作更新。显示的<Route>显示的是新数据,但是是错误的<Route>

应用的基本结构是:

<Root>                                  (custom)
  <Provider>                            (react-redux)
    <ConnectedRouter>                   (connected-react-router)
      <App>                             (custom)
        <Switch>                        (react-router-dom)
          <Route path="/" exact />      (react-router-dom)
          <Route path="/quality:q" />   (react-router-dom)

最初我们导航到根目录,&lt;Route path="/&gt; 正确显示。我们单击一个链接,该链接正确地将我们带到&lt;Route path="/quality/:q" /&gt;。从那里我们返回浏览器,URL 更改为 /,但 &lt;Route path="/quality:q" /&gt; 仍然显示,但它不应该再显示了。

Redux devtools 显示了这个渲染树,我在其中包含了一些由我们明确使用的组件添加的关键组件。

<Root>                                  (custom)
  <Provider>                            (react-redux)
    <ConnectedRouter>                   (connected-react-router)
      <Router>                          (injected)
        <Context.Provider>              (injected)
          <App>                             (custom)
            <Switch>                        (react-router-dom)
              <Route path="/" exact />      (react-router-dom)
              <Route path="/quality:q" />   (react-router-dom)

当处于这种错误状态时,直到&lt;ConnectedRouter&gt; 的所有内容都是正确的。 &lt;ConnectedRouter&gt; 有一个单独的 prop,它是 history,它具有正确的位置,即根。

紧随其后的&lt;Router&gt; 不匹配。它有一个 history 属性,没问题,但它有一个陈旧的 location 状态,显示旧网址。

当错误的位置数据被上下文传递给&lt;Route&gt;s 时,他们会从location 属性中获得检查路径,该属性匹配&lt;Router&gt; 的陈旧状态。结果,渲染了错误的&lt;Route&gt;

我无法弄清楚我做了什么导致这种不匹配。这都是简单的路线,并使用&lt;Link&gt; 组件作为从主页到子页面和返回的所有链接。

以前有没有人见过这个和/或可以指出如何解决这个问题的方向?

【问题讨论】:

  • 我遇到了类似的问题,history.location 正确但 location 不正确,您能找出原因吗?

标签: reactjs react-router react-router-redux connected-react-router


【解决方案1】:

我认为您的路由结构需要重构,因为您尝试匹配(可能是嵌套的)URL。

如果您希望/quality/:id 低于/,则Route 需要是component 的子代。

例如,Route 将是:

<Route path="/" component={Home} />

然后在Home 组件中,您将拥有使用match.url (route props) 作为字符串匹配器的子Routes:

const Home = ({ match: { url } }) => (
 <>
  <div>Home<Home>
  <Switch>
    <Route path={`${url}quality/:q` component={Quality} />
    <Route path={`${url}some/other/route`} component={Example} />
  </Switch>
 </>
);

但是,如果您想要相反的情况,即/ 独立于/quality/:p,那么您需要使用exact

<Switch>
   <Route exact path="/" component={Home} />
   <Route exact path="/quality/:p" component={Quality} />
   <Route exact path="/some/other/route" component={Example} />
<Switch>

工作示例

在本例中,/home/about/dashboard 是相互独立的路由;但是,/dashboard 是这些子路由的父级:/dashboard/settings/dashboard(顺序很重要!)和 /dashboard 呈现一个 Dashboard 组件,它也恰好是 /dashboard/profile 子路由的父级! Order 和 exact 对于每个嵌套路由的渲染方式很重要。我还在pages/Profile 中包含了一个goBack 示例,以证明connected-react-router 的历史记录与react-router-dom 路由历史记录路由保持一致。

demo

source


如果您遵循上述约定,那么唯一的另一个问题是react-hot-loader 正在阻止状态更改。我个人不使用 RHL,因为我发现它相当有问题,但对每个人来说都是如此。也就是说,我在过去的 3 或 4 个项目中使用了connected-react-router,并且我从来没有遇到过 props/state 不匹配的情况(除了一些共享的 redux 数据是陈旧的并且需要在加载另一个组件之前重置)正在重用相同的数据结构)。

【讨论】:

  • 感谢您的回复。在简化发布消息时,我在根路由上省略了 exact 关键字,但它在原始代码中。我更新了问题以澄清。
  • 如果您可以创建可重现的代码和框演示(不需要花哨),那么它会更容易提供帮助。否则就是猜谜游戏。
  • 同意,如果我可以重新创建,我可能会找到它。我正在逐行还原并重新应用自上次已知工作版本以来的更改,以查看导致此问题的原因。
  • 要考虑的另一件事是,如果您使用的是服务工作者,那么它可能会缓存您的请求。
  • @SamuelNeff - 你最终解决了这个问题吗?如果是这样,解决方法是什么?
【解决方案2】:

如果您使用 react-router 5+,您可以将位置从上层范围传递到 Switch。我从历史背景中传递过来。在我的情况下它解决了同样的问题

【讨论】:

    【解决方案3】:

    我遇到了类似的问题。事实证明,我的树上有一个PureComponent 导致了它。使用withRouter 并将location 传递给PureComponent 解决了这个问题。

    import { withRouter } from "react-router-dom";
    
    const App = withRouter(({ location, children }) => (
      <IntlProvider location={location}>
        {children}
      </IntlProvider>
    ));
    
    ReactDOM.render(
      <Root>
        <Provider>
          <ConnectedRouter>
            <App>
              <Switch>
                <Route path="/" exact />
                <Route path="/quality:q" />
              </Switch>
            </App>
          </ConnectedRouter>
        </Provider>
      </Root>
    

    【讨论】:

      猜你喜欢
      • 2021-08-25
      • 2021-10-27
      • 2020-10-29
      • 1970-01-01
      • 2011-12-31
      • 2013-01-14
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      相关资源
      最近更新 更多