React Router 仅在第二次单击后更新
React Router only updating after second click
所以,基本上我有多个嵌套路由,如 /:platform/:account/products/:tab/:productId/summary
。
一直到我实际的单一产品组件,一切都正常,但 react-router 在我的单一产品选项卡中停止正常工作。
我有一个带有选项卡(路线)的产品视图,当单击一个项目时,会出现一个弹出窗口,它是单个产品视图,里面还有 3 个选项卡。
我的产品的子路由正在更新,但仅在下一个渲染周期。
- 我在摘要中并单击价格:没有任何反应
(路线更改为
/:platform/:account/products/:tab/:productId/prices
)
- 我单击摘要:渲染组件更改为价格
(路线更改为
/:platform/:account/products/:tab/:productId/summary
)
- 我点击 Translations: Rendered component changes to Summary
(路线更改为
/:platform/:account/products/:tab/:productId/translations
)
- 我再次单击 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
如果您使用嵌套的 Route
或 NavLink
(路由的包装器),您将需要使用 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 提供位置,上下文将成为新的上下文并将其提供给子路由。它会按预期工作。
所以,基本上我有多个嵌套路由,如 /:platform/:account/products/:tab/:productId/summary
。
一直到我实际的单一产品组件,一切都正常,但 react-router 在我的单一产品选项卡中停止正常工作。
我有一个带有选项卡(路线)的产品视图,当单击一个项目时,会出现一个弹出窗口,它是单个产品视图,里面还有 3 个选项卡。
我的产品的子路由正在更新,但仅在下一个渲染周期。
- 我在摘要中并单击价格:没有任何反应
(路线更改为
/:platform/:account/products/:tab/:productId/prices
) - 我单击摘要:渲染组件更改为价格
(路线更改为
/:platform/:account/products/:tab/:productId/summary
) - 我点击 Translations: Rendered component changes to Summary
(路线更改为
/:platform/:account/products/:tab/:productId/translations
) - 我再次单击 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
如果您使用嵌套的 Route
或 NavLink
(路由的包装器),您将需要使用 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 提供位置,上下文将成为新的上下文并将其提供给子路由。它会按预期工作。