React Router 仅在第二次单击后更新

React Router only updating after second click

所以,基本上我有多个嵌套路由,如 /:platform/:account/products/:tab/:productId/summary。 一直到我实际的单一产品组件,一切都正常,但 react-router 在我的单一产品选项卡中停止正常工作。 我有一个带有选项卡(路线)的产品视图,当单击一个项目时,会出现一个弹出窗口,它是单个产品视图,里面还有 3 个选项卡。

我的产品的子路由正在更新,但仅在下一个渲染周期。

  1. 我在摘要中并单击价格:没有任何反应 (路线更改为 /:platform/:account/products/:tab/:productId/prices
  2. 我单击摘要:渲染组件更改为价格 (路线更改为 /:platform/:account/products/:tab/:productId/summary
  3. 我点击 Translations: Rendered component changes to Summary (路线更改为 /:platform/:account/products/:tab/:productId/translations
  4. 我再次单击 Translations:Rendered component 更改为 Translations (根本没有改变路线)

我已经为此奋斗了 4 个多小时,我检查了我的树中是否有任何 PureComponent,我几乎到处都使用了 withRouter,我还检查了我的产品组件是否没有更新(也许我的主视图组件阻止了更新),但一切似乎都很好,新道具是正确的。 我也尝试在 connect() 中使用 { pure: false } 但没有任何帮助。 为了以防万一,我还删除了这个 localize HOC,但这并没有解决问题。

版本

4.2.0

示例代码

这是我的组件中的精简渲染方法:

class ProductView extends Component {
  componentWillReceiveProps() {
    console.log("UPDATED PRODUCT TAB")
  }

  render() {
    const { match, history, translate, lang, loading, data } = this.props
    console.log(match)
    return (
      <Modal>
          <TabList>
        <TabItem>
          <NavLink
            activeClassName="active"
            to={{
              pathname: `/${match.params.platform}/${match.params.account}/products/${match.params.tab}/${match.params.productId}/summary`,
              search: location.search,
            }}
          >
            {translate("Summary")}
          </NavLink>
        </TabItem>
        <TabItem>
          <NavLink
            activeClassName="active"
            to={{
              pathname: `/${match.params.platform}/${match.params.account}/products/${match.params.tab}/${match.params.productId}/prices`,
              search: location.search,
            }}
          >
            {translate("Prices")}
          </NavLink>
        </TabItem>
        <TabItem>
          <NavLink
            activeClassName="active"
            to={{
              pathname: `/${match.params.platform}/${match.params.account}/products/${match.params.tab}/${match.params.productId}/translations`,
              search: location.search,
            }}
          >
            {translate("Translations")}
          </NavLink>
        </TabItem>
      </TabList>
          <Switch>
            <Route path="/:platform/:account/products/:tab/:id/summary" component={Summary} />
            <Route path="/:platform/:account/products/:tab/:id/prices" component={Prices} />
            <Route path="/:platform/:account/products/:tab/:id/translations" component={Translations} />
          </Switch>
      </Modal>
    )
  }
}

const mapStateToProps = state => (...)

const mapDispatchToProps = dispatch => (...)

export default withRouter(connect(
  mapStateToProps,
  mapDispatchToProps,
)(localize("translate")(ProductView)))

到达产品组件的路线如下所示: <Route exact path="/:platform/:account/products/:tab/:productId/:productTab" component={ProductView} /> 添加或删除 :productTab 没有区别。 在具有此产品路线的组件内,我还有其他 NavLinks 用于选项卡,路由器工作正常。

奇怪的是,组件一直更新到我的产品路线,具有正确的 match 道具,但那些子路线,包括 NavLinks 仅在再次点击后更新。

React-redux 在其 connect 函数中实现了纯渲染。所以这可能会阻止您的更新

像这样尽早使用 withRouter。它将阻止 connect 阻止来自路由器的更新。

export default connect(
  mapStateToProps,
  mapDispatchToProps,
)(localize("translate")(withRouter(ProductView)))

所以,我设法找到了它(不知道为什么我在 3 小时前没有尝试这个......)并发现它是由于 react-modal。

还有其他人遇到同样的问题,这是工单: https://github.com/reactjs/react-modal/issues/499

如果您使用嵌套的 RouteNavLink(路由的包装器),您将需要使用 Switch(方便起见)来包装所有模态内容(或至少使用 Route/NavLink).

的部分
const location = (this. - if you component is not a function)props.location;
<Switch location={location}>
  <NavLink ... />
  <Route ... />
</Switch>

这将确保更新位置。

react-modal不干扰用户组件的更新。 Routes 接收到的 location 来自 getChildContext(),它只会在 React 组件生命周期之后更新。通过在 render() 上为 Switch 提供位置,上下文将成为新的上下文并将其提供给子路由。它会按预期工作。