-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[v4] Breaking Changes #4699
Comments
On the topic of breaking changes: what happened to the |
v4 is a complete rewrite. As such, there is no singular breaking change. We have some similar-looking things ( As for the on* hooks, they were removed because they already exist in React as the lifecycle methods. We were reimplementing them inside the Router, but they didn't exactly behave like they should. So, why provide an inferior or conflicting API? Everything is way more React-y now, and it's way better as a result. You no longer have to mix paradigms or code for two different systems. It's just React now. It's a much lower cognitive load. And for "plain routes", we've extracted that to a separate package: https://github.com/ReactTraining/react-router/tree/master/packages/react-router-config You can see the reasoning for this here: #4410 (comment) |
@timdorr - re: "they were removed because they already exist in React as the lifecycle methods" What in the world are you talking about? Are we supposed to subclass Route and override componentDidMount and componentWillReceiveProps or something? It sure doesn't seem like there's an easy way to implement an onEnter or onLeave hook in V4. |
@johnomalley The lifecycle methods get placed on the component rendered by the |
Yeah, did a dry run of converting v3 -> v4 and it's going to be super-painful on my project. The nice thing about the onEnter/onLeave handlers is that I would write my containers in my redux app so that they were only dependent upon the store state. Now I have to extract the path variables (e.g. something like itemId in /items/42) from the 'match' prop and update the store that way. On top of the lifecycle methods require that I can no longer use stateless functional components and need to implement React lifecycle methods just to make the router integration work. I think I'm staying with v3 for the foreseeable future. The v4 code is just a lot uglier. |
@timdorr how do you prevent a route change now then? This seems to be a large loss in functionality as far as the |
@arempe93 I bet now we have to use component Which is in my opinion much better than calling |
@Johnius that seems helpful for prompts, but not for what I had in mind. A pattern that I use, and I think is common, is to wrap my routes that require login in a export default function createRoutes(store) {
return (
<Route component={App} path='/'>
<Route component={Login} path='/login' />
<Route component={Authenticated} onEnter={Authenticated.enter(store)}>
<IndexRoute component={Dashboard} />
...
</Route>
</Route>
)
} And the (nextState, replace, callback) => {
if (<logged in>) {
if (<! store has user data>) {
store.dispatch(fetchCurrentUser())
.then(() => callback())
}
} else {
replace('/login')
callback()
}
} I assume that v4 expects me to have instead have a wrapper component in the EditLooking over the docs more - it seems like What I would recommend to the maintainers is to elaborate more on the on* section of the migration doc. It's a bit sparse and could use examples of how to handle |
We're trying to sync breadcrumbs with the router in our project and not having an event fired or a callback in the components is very ugly. There is no way we can implement this "generic" hooks in each and every single component rendered by a route. Maybe we should try v3 |
@jfconde to avoid making your components "ugly" you can create a |
@rizedr Yes! Thank you! In the end I solved this using a HoC as you suggest. My HoC might be a bit of an anti-pattern, since it makes all "routed components" connected to Redux. Basically, it allows each of the routed components to have a defined title, and each time one of them is mounted or unmounted, a PUSH/POP_BREADCRUMB action is automatically dispatched (we could have passed props to these components, but then IDK if we could have used the clean Each routed component also gets a unique breadcrumbId, in order for a "dynamic title" to be managed (ie: you're loading a product with id: X called "Chair" in a component with title "Product detail" and in the breadcrumbs you want to show "Chair", but you will not have this info until the serverresponds but since the breadcrumb has an id we can replace "Product detail" with "Chair" using such id). I think it looks a little dirty (dispatching from a HoC 👎 ), but for the time being (we don't have much time to refactor until our first deadline) it works, and breadcrumbs are automatically managed (we just use a dumb component to read the breadcrumbs array from the redux state and convert ['Home', 'Section', 'Sub-section'] into buttons like Home > Section > Subsection). Here's the "BreadcrumbManager" code looks like: https://pastebin.com/0sv9tYzK |
@jfconde Looks pretty good IMO - I don't see any issue in having all route components connected to redux. You can fix the "dirty" part by using the
|
The simple answer. import React from 'react';
import {
Route,
Redirect
} from 'react-router-dom';
const RouterCreate = (props) => {
return (
(props.onEnter !== undefined ?
(props.onEnter() ?
<Route {...props} />
:
<Redirect to="/login" />
)
:
<Route {...props} />
)
);
}
export default RouterCreate; Usage: <BrowserRouter>
<div>
<Navbar />
<Switch>
<RouterCreate exact path="/" component={HomePage} onEnter={isLoggedIn} />
<RouterCreate exact path="/login" component={() => isLoggedIn() ? <Redirect to="/" /> : <Login />} />
<RouterCreate exact path="/protectedroute" component={ProtectedRoute} onEnter={isLoggedIn} />
<RouterCreate exact path="/currency" component={Currency} onEnter={isLoggedIn} />
<RouterCreate exact path="/logout" component={Logout} onEnter={isLoggedIn} />
<RouterCreate exact path="/about" component={About} onEnter={isLoggedIn} />
<Route component={() => <Redirect to="/" />} />
</Switch>
</div>
</BrowserRouter> |
@arthurhoch you don't consider onEnter is async. onEnter should have a callback |
The same idea was reflected in #4697, but that part was ignored, therefore opening a new issue to specifically address that.
I can see that v4 is coming up with the pre-releases from the past days to which I can only say congrats 👍
However, I cannot see anything about the very useful hooks that were available in v3:
Furthermore, I do not see anything to reflect the above decision in the change log, nor cannot find a roadmap that describes this methods are deprecated. Should I expect v4 will break all my code?
I find this hooks very useful, for example, I was using the
onEnter
hook to validate if the user is authenticated in a very elegant way compared to the way is illustrated in the v4 docs. In my opinion, my solution works better because I need the user to be authenticated on all pages except/login
.Another thing I cannot find with v4 is Configuration with Plain Routes, where, why did that go?
Maybe let's not close this right away and use this forum to debate as this package is essential in my projects and, hopefully, this will end in a clear roadmap for all of us.
The text was updated successfully, but these errors were encountered: