代码之家  ›  专栏  ›  技术社区  ›  Samuel Neff

“后退”按钮后的“历史记录”和“位置”不匹配

  •  0
  • Samuel Neff  · 技术社区  · 5 年前

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

    文件的内容 <路线> 做改变;数据通过位置更改Redux操作进行更新。展示 <路线> 显示新数据,但它是错误的 <路线> .

    该应用程序的基本结构是:

    <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)
    

    最初,我们导航到根和 <Route path="/> 正确显示。我们点击一个链接,正确地将我们带到 <Route path="/quality/:q" /> .从那里我们点击浏览器返回,URL变为 / 但是 <Route path="/quality:q" /> 仍然显示,但不应该再显示了。

    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)
    

    在这种不正确的状态下,所有 <ConnectedRouter> 这是正确的。 <ConnectedOuter> 只有一个道具 历史 它有正确的位置,根。

    这个 <路由器> 就在它下面是不匹配的。它有一个 历史 道具没问题,但它有一个陈旧的 location 处于显示旧url的状态。

    当坏位置数据被上下文传递到 <路线> 他们从他们的 地方 哪一场比赛 <路由器> 陈腐的状态。结果,错误的 <路线> 是渲染的。

    我不知道我做了什么导致了这种不匹配。这都是直截了当的路线和用途 <Link> 从主页到子页面的所有链接的组件。

    以前有没有人见过这个问题,或者可以为我指出如何解决这个问题的方向?

    Screenshot of mismatched props and state

    0 回复  |  直到 5 年前
        1
  •  2
  •   Matt Carlotta    5 年前

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

    如果你愿意 /quality/:id 倒下 / ,然后 Route 需要成为一个孩子 component .

    例如 路线 将是:

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

    然后在 Home 你会有孩子的 路线 那有什么用 match.url ( route props )作为字符串匹配器:

    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/settings /仪表盘 (秩序很重要!)和 /仪表盘 呈现 Dashboard 组件,该组件恰好也是 /dashboard/profile 儿童路线!秩序和 准确的 对于每个嵌套管线的渲染方式很重要。我还包括了一个 goBack 里面的例子 pages/Profile 为了证明这一点 connected-react-router 中国的历史与中国保持一致 react-router-dom 路由历史路由。

    demo

    source


    如果你遵循上述惯例,那么唯一的另一个问题就是 react-hot-loader 正在阻止状态变化。我个人不使用RHL,因为我发现RHL相当有问题,但每个人都有自己的问题。也就是说,我用过 连接路由器 在我过去的3到4个项目中,我从来没有遇到过道具/状态不匹配的情况(除了一些共享的redux数据过时,需要在加载另一个重用相同数据结构的组件之前重置)。

        2
  •  0
  •   Birulia Katerina    5 年前

    如果您使用react router 5+,您可以将位置从上范围传递到交换机。我从历史背景中经过。它解决了我的问题

        3
  •  0
  •   Chad Watson    4 年前

    我也有类似的问题。原来我有一个 PureComponent 在我树上的某个地方导致了它。使用 withRouter 并通过 location 进入 纯组分 解决了这个问题。

    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>