-
-
Notifications
You must be signed in to change notification settings - Fork 5k
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
Support thread: migrating away from Redux integration #4490
Comments
This can also help people: here's an open source example of removing the Redux integration (+ upgrading to v2): DailyScrum#28 |
I think it's useful to explain a bit more why it's being deprecated. |
Hello. It will be nice if instruction how to change navigation from redux actions will be provided. |
@lintonye - nobody has been able to provide any compelling reasons for why it is worth the additional complexity and support surface area (see
|
can you explain this further? I don't follow |
Supporting redux integration is a burden for the core team, unfortunately. We need to focus on making the core of the library rock-solid for all users, and its extremely challenging when people frequently report issues that are caused by a complicated redux setup and cannot be reproduced with react-navigation alone. We will continue to support controlled navigators, so advanced users can manage their own navigation state. But all bugs must be filed with a reproduction example with only the core library, so that we can clearly see the issue, independent of your redux/mobx/whatever setup. |
This is a bit sad. In some apps I'm using the redux integration to manage navigation transitions through action streams in redux-observable, which makes for some nice flows. If the integration is to be gone, I'll have to manage the navigation transitions through the React lifecycles when props change instead (?) and call the navigation functions inside the lifecycles. Which may not be that bad, but certainly not nicer. Edit: I see your issues, but if you continue to support controlled navigators wherein we can manage our own state that's awesome @ericvicenti. |
Your use-case definitely won't break @hanse. But you may need to fork or help maintain |
you can also use this approach to get a global reference to the navigation object |
Like @hanse I have almost all navigation logic in redux asynchronous actions (redux-thunk mostly). For example, on start up I'm waiting until redux is filled with user data (authentication etc.) and then I'm making a decision to show login screen or app itself. All this logic within redux-thunk action like:
So it will be nice if docs will provide some alternative to |
@brentvatne what about dispatching navigation actions outside a component? now I'm using it heavily |
@brentvatne What about dispatching as a result of a redux-saga? Similar use case of @DimitryDushkin |
same thing @diegolmello ^ |
Thanks! Probably should be mentioned in new "Integration with redux" part. |
@brentvatne Without rudux, how can data be communicated across components? For example, I got a token on a login page. I hope all pages know that the user is already logged in. |
you can use redux all you want, we're just saying you shouldn't put the navigation state in redux |
This is sad. It has been extremely helpful for keeping the application state predictable and control navigation from redux middleware etc. That said the redux helper library is certainly not that well maintained and was super relatively easy to replicate after reading the react navigation source code, so I rolled my own by now which provides a bit different way to setup routes, thinking about open sourcing that. So I hope that routers of navigators will stay available and there will be support for controlled navigators past v3 as well, than it’s fair that maintaining such integrations are up to developers and not part of the core. |
@MrLoh - the plan is to keep controlled navigators around.
two parts to this:
this is very abstract, can you elaborate? I don't understand
you can do this using the pattern described in https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html |
The main thing is about having the navigation state in redux is that I can super easily get the current stack that I am on and all the info about the navigation variables in every reducer and redux middleware. I migrated away from react-native-navigation specifically to prevent the necessity of tracking my navigation state in another place as well, but have a predictable navigation state right were the rest of my state lies and understand the whole logic behind it. It's more about reading the state than about changing the state. But as long as it is still possible to have controlled navigators and access the router of the navigator to produce my state I'm fine with this being discouraged and I totally get the problem, that this is a lot of effort to maintain and you get questions from people who don't know what they are doing. |
it sounds like you like to have this control but you're not actually using it? I haven't heard concrete use cases except that you want to control navigation from middleware. anyhow, if that's how you want to do your app and you're wanting to understand everything, that seems fine! i'm more interested in getting people who put their nav state into redux because "why not?" or some other easily solvable problem to go back to a standard setup. |
I mean there are some concrete usecase in my app, where I do fire side effects on a navigation action. For example firing analytics or setting a dark theme for a specific route and resetting it when I am going back from that route and triggering certain prefetches of data and intializations of services. I could probably do all of this in componentDidMount and willUnmount callbacks as well. But this way state and UI Design are clearly separated and the redux actions are just a great abstraction for what happens in the app. In the end an engineer that works on the state at our startup has a much easier time, if he doesn’t also have to read a ton of React code to understand what’s going on. But the whole state machine lives in redux. But yeah you are right it’s all a design choice, but that’s what makes the biggest difference in productivity from day to day in the end in our team and good abstractions are valuable. As our app grows from 5 to 50+ routes, abstraction gets better and better and right now no one has to understand react navigation to build anything, but there’s just one place to register a new route and everything else is firing redux actions. Just please don’t cut down all advanced features because this library is overrun by people who are building their first app and have a hard time getting things to work and start creating issues here that are just questions about the library. I’m a little frustrated about the React native ecosystem in terms of how hard it is to get forward on hard issues at the moment, there’s just so much noise. Whenever I ask a hard question in a forum or on github there are no responses these days and I do always try to answer a few easy questions people ask to help them out, but it’s super hard to find help with hard topics. I think the mantra of making easy things easy and hard things possible is good though. And you are doing an amazing job of keeping this all under control and providing a remarkably stable library that provides immense value. |
We just migrated away from the react-navigation redux integration and opted to take advantage of the NavigationService approach, as outlined here: https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html. We were using the redux integration to allow us to fire navigation actions from within a saga, such as to direct the user to the appropriate screen based on login state. We're running into a race condition issue where the NavigationService isn't initialized in time to receive the navigation request. You can see the issue in this snack: https://snack.expo.io/Hkj3okzb7 (Be sure to look at the logs to see the "uncaught at rootSaga" error.) We've temporarily worked around the issue by caching any navigation actions that are requested before the navigator ref is set, and dispatching them inside setTopLevelNavigator(). Has anyone else run into this issue? Any better approaches? |
@aatreya I currently just face the same problem. I do the same approach. Queue the dispatched actions, and pop when setTopLevelNavigator is called. Hello. First of all, I just want to say, react-navigation is trully great library! 🙇You guys are awesome. There're 2 functionally which I used integration react-navigation with redux in my project.
Please tell me if there's a better approach, it would great help for us. |
For those of you who are wondering how to listen for the actions dispatched by a redux detached navigator, I found it really useful the |
I somehow understand the reasoning behind this . Nevertheless I am missing some features to ultimately moving away from my external state management solution (mobx in my case). Is there any callback planned like |
I just migrated from a react-navigation/redux integration and put the NavigationService approach into place. In general I'm a fan of the increased simplicity particularly since we had yet to make sure of the redux integration. I am also experiencing th problem others have reported of the navigation object not being available when the first navigate request is sent to it. A queue approach seems like it will do the trick. @declandowling the cached routes/params approach you posted looks great but fails in a situation where a persistenceKey has been set. It seems react-navigation tries to repeatedly apply the persistenceKey filling the arrays with thousands of navigate requests until the app crashes. I tried wrapping the array push with conditionals that checked if the route/params already existed prior to adding but React is throwing an Invariant Violation error. I'm not sure what the proper way to do this is. As a temp hack I've implemented a setTimeout delaying the NavigationService.navigate call but would like to remove this before shipping my project to avoid potential race conditions and improve performance. |
The recommended alternative approach using a ref isn't great IMO. It just feels really kludgey. I generally avoid refs as much as possible because I'm trying to push side effects out of my components aggressively: this is why I'm using Redux (and React) in the first place TBH. I'm loathe to add a ref grabbing side effect. I'll probably to end up using Navigating is a side effect. It belongs in action creators (or epics). I'm willing to be convinced about whether keeping the router state in the store breaks encapsulation in ways that make your lives difficult but having to grab a component reference in order to navigate from outside components is something I'm struggling with philosophically. We're basically faking a singleton at this point.
Exactly ^. Temporal dependencies like this are a big part of why refs/singletons like this are bad idea. |
As an aside I love putting location state in the store. It means I can time travel over it and use it in state derivations like any other state. It also means navigation is properly treated as part of the action stream like any other user or system action. Some elaboration as to why you think it's a bad idea would help; the only think I can thing of is that it makes it hard for you to change the lib unless you formalize the shape of the state and treat it as a first class part of the API. But then my background is web where navigation is much less complex. |
Exactly how I feel Seth. I’ll simply keep up my own redux integration, until it becomes impossible. Navigation state in redux is definitely the clean way to do things. |
I had a lot of trouble getting things to work without redux integration in a new little app I was building. the nav reference implementation seems quite buggy. On Android I had 20% crashes of my app, because the ref just returned null. Maybe it is the combination with the persistence? I am looking for a workaround to the nav reference now, but my takeaway is that I am definitely not moving my main app away from the redux integration, which is at least transparent in how it works and will fork react-navigation to continue a proper redux integration in the future if necessary. |
as for why it is necessary to call navigation actions from outside of screens: there is logout in response to network unauthorized errors, reacting to notification presses depending on where you are in the app, firing network requests upon route changes. Sure all this can be done in componentDidMount handlers as well. But that is the same as saying, you can do everything you can do with redux without it as well, wich is very true, but redux helps to structure code better and make it more transparent. Moving essential parts of the global state out of redux doesn't work well. And keeping the states in sync is always more buggy than just having a single source of truth. |
Also: deep-lining in run-time. If app should handle some url after app launch. I can't imagine better place other than redux middleware for that. Specially if I need some make requests before navigation or wait for current io complete. I think there is not place for handling external events using components. |
👋 - I'm migrating our app away from redux and I've implemented a navigationService as per the docs, but I can't seem to get it to work when the top level navigator is a Is it meant to work with a |
@kadikraman - I'm having exactly the same issue. When the top level navigator is |
@AdamPD mine works now, though I'm not sure why. Just tried it on a completely fresh install as well 🤨- when debugging it I was logging out the navigation state and mixing around the initial routes in the nested nav in Finished our migration last night. Final count:
& 8 of these previously had navigation state in redux. |
Hi, I´m learning React Native to make an App. the problem is that in the components this.props is: my main code is some like this:
|
The one good example we have in our project is integration with Sentry. We can easy control each action which goes to store and log them to Sentry. So we don`t have to catch them in different places in the app |
@brentvatne You seem to be doing a great job of assisting people on this thread. Please see my snack at https://snack.expo.io/@cush/navigationservice - I'm struggling to get the "navigating without the navigation prop" example working. I need to retain the navigator in its own component because I'm planning on wrapping it in a component once I integrate redux with this. All help is greatly appreciated as I'm fairly new to the library (and RN in general) so it might just be a stupid, simple-to-see error for more experienced devs EDIT: I also raised an issue for this on this very repo . It says closed, but that was a likely mistake from a collaborator. The issue remains very much at large |
Just my opinion: The thinking behind "Are there any particular use cases that redux integration supports" and "how can we support everything that people want to do with redux integration without it" is missing the more important issue. State management is probably the single biggest problem an app has to solve. Redux is a great and simple solution to that problem. So many things are easier when all state is in redux or some such thing.
Having other libraries/frameworks like react-navigation storing their own state separate from redux is fundamentally incompatible with this good design. It's not about peculiar use cases specific to routing, its about maintaining a consistent and good app design. Some examples of things that go wrong as a result of keeping state outside of redux:
If the only important aim of react-navigation is having a super simple "hello world" example without any dependencies, redux middlewares, etc, then I see why redux integration is not a priority. But if the aim is to be a library that integrates well with more complex apps and lends itself to a good app design, then I think easy and reliable/supported redux integration is a must. This article by @faceyspacey is a great read about app design with redux and how to implement a clean MVC architecture in the JS ecosystem. Pretty much everything there applies just as much to react-native apps as react web apps. Think about how easy universal linking would be. |
Couldn't agree more or say it better myself. When the state of an app get's to certain level of complexity it just becomes soo much easier to handle it in redux and the real challenge of a good router is not to get started quickly for the thousands of test projects people create (even though it's obviously great if that is possible too), but to make routing manageable in apps at scale and support the complexities of growing apps in production. Unfortunately the voices of all the people with small test projects getting started will always overpower the voices of people with complex problems in production. Redux is good architecture, good architecture means you don't have to for-see all possible problems you will run into, but you're code will have your back, when you run into the unforeseen complexities the will inevitably come up in a project as it grows. |
So what's the outcome, in the documentation it looks like there's been a bit of back flip... Extremely confusing to find the solution to the getChildNavigation problem that is faced when integrating the redux state with Navigation. Some pointers would be really appreciated... Even react-navigation-redux-helpers seems to cover little in the way of handling these changes. |
I'm struggling migrating from My code looks like so currently:
|
@declandowling @brentvatne regarding to this problem that I had too (#4490 (comment)) I don't know if it's feasible for you, it highly depends on the way you structured your code, but I personally have an action creator bound to my first screen of the switch navigator (that is the route always opened at the startup of the app) and I decided that the cleanest and fastest solution to that "undefined" problem, is to pass the navigate function from the component to the bootstrap action creator. It's quirky for sure, but can I know @brentvatne why this happens? I mean, why the navigator is rendered but the ref is not set yet? Couldn't you postpone the rendering AFTER you set the ref? |
What are the main use cases that are no longer supported? I don't understand how storing the navigation state and dispatching navigation actions in redux would cause problems. Thanks! |
Hello 👋, this issue has been open for more than 2 months with no activity on it. If the issue is still present in the latest version, please leave a comment within 7 days to keep it open, otherwise it will be closed automatically. If you found a solution on workaround for the issue, please comment here for others to find. If this issue is critical for you, please consider sending a pull request to fix the issue. |
Do you have plans to bring back the ability to persist navigation state in redux? This method provides useful and simpler control over your application. I used to be able to save my current application time travel log and send it to a developer or anyone else to open it in redux-devtools to observe the wrong behavior without reproducing. From now, I can't do this because importing of the time travel logs does not change screens. And your tool useReduxDevToolsExtension doesn't work with export / import too |
If you are using Redux integration, we recommend migrating away from it soon. The Redux integration docs page will be updated shortly with the following:
Please use this thread to get help on any issues you encounter when moving away from Redux integration to a vanilla React Navigation setup.
The text was updated successfully, but these errors were encountered: