Reputation: 553
So, basically I have multiple nested routes like /:platform/:account/products/:tab/:productId/summary
.
Everything works fine down to my actual single product component, but react-router stops working properly in my single product tabs.
I have a products view, with tabs (routes) , and when clicking an item, there's a popup that is the single product view, which, has 3 more tabs inside.
The child routes of my product are updating, but only on the next render cycle.
/:platform/:account/products/:tab/:productId/prices
)/:platform/:account/products/:tab/:productId/summary
)/:platform/:account/products/:tab/:productId/translations
)I've been fighting with this for over 4 hours, I checked if I had any PureComponent
in my tree, I used withRouter
pretty much everywhere, I also checked if my product component was not updating (maybe my main view component was blocking the update), but everything seems fine, new props are correct.
I also tried using { pure: false }
in connect()
but nothing helped.
I also removed this localize
HOC just in case, but that didn't solve it.
4.2.0
Here is a stripped down render method from my component:
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)))
The Route to get to the product Component looks like:
<Route exact path="/:platform/:account/products/:tab/:productId/:productTab" component={ProductView} />
Adding or removing :productTab
makes no difference.
Inside the component with this Product Route I have other NavLinks
for tabs and Router is working correctly.
What's weird here is that components update all the way down to my Product Route, with correct match
props, but those child Routes, including NavLinks only update after another click.
Upvotes: 4
Views: 2332
Reputation: 36
If you are using nested Route
or NavLink
(a wrapper of Route), you will need to use Switch
(as convenience) to wrap all the modal content (or at least the part which uses Route/NavLink).
const location = (this. - if you component is not a function)props.location;
<Switch location={location}>
<NavLink ... />
<Route ... />
</Switch>
This will make sure that the location will be updated.
react-modal
does not interfere on the update of user components. The location
that the Routes receives comes from getChildContext()
, which only updates after the react component lifecycle. By giving to Switch the location on render()
, the context will be the new one and it will be given to the children Routes. It will work as expected.
Upvotes: 2
Reputation: 553
So, I managed to track it down (Not sure why I didn't try this 3 hours before...) and figured out it's due to react-modal.
There's someone else with the same issue, here's the ticket: https://github.com/reactjs/react-modal/issues/499
Upvotes: 0
Reputation: 2201
React-redux implements pure render in its connect
function. So that might be blocking your updates
Try using withRouter
early like this. It will stop connect
from blocking updates coming from router.
export default connect(
mapStateToProps,
mapDispatchToProps,
)(localize("translate")(withRouter(ProductView)))
Upvotes: 0