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
screenIsActive prop / componentDidFocus event for TabNavigator items #51
Comments
Use |
but how do you get the active route? |
|
will log: |
It probably makes sense to add lifecycle hooks to screens. So on your screen component you could declare:
What do people think about that? |
@ericvicenti sounds good, though we need to think about it a bit more. this is probably clear for stack navigators, but
|
@JohannesKaufmann have you checked the tab navigator docs? there's an option called |
We need to pass props to the TabView but we don't or has that changed? |
@browniefed nope. I think we need to discuss it first, since it'd be weird to have some props passed when rendering, and some props passed when creating the navigator. I'll open an issue regarding that. |
I'd like just to chime in here coming from extensive usage of React Router v4 where they explicitly backed away from lifecycle hooks. If we can at all avoid adding lifecycle hooks, I'm all for it. These lifecycle hooks add complexity and, IMHO, are not part of React's basic philosophy. Not that my opinion really matters ;-) Why not use what we already have -- props to signal a component's current state? Can't the usual lifecycle hooks cover most or all cases at that point? I might be missing some stuff here. @satya164 can you show me a quick example or provide more detail of the creating vs rendering concern here? |
What about a higher order component that gives you more information about the current routing state? Or maybe some way to register to the |
It won't if you don't to expensive work during the animation componentDidMount() {
InteractionManager.runAfterInteractions(() => this.setState({ ready: true });
}
render() {
if (!this.state.ready) {
return <PlaceholderWithIndicator />;
}
...
} |
Which concern are you talking about? |
Pretty sure this won't be noticeable when you're in production mode |
@satya164 In As I'm currently using |
If it's noticeable in production mode, then it's something we need to fix.
Animation performance is sure important, regardless of which navigator you use. We use native animations where we can, so animation performance should be good, if you see animation is janky somewhere, please file an issue. Remember that this library is still in beta. |
@hilkeheremans I do appreciate that lifecycle hooks should be used sparingly. We got this far and we haven't needed them, but there are often things in real-world apps that demand this use case. Just like most things with react, the declarative API is what you almost always want to use, but occasionally, imperative lifecycle hooks are needed. One of the greatest things about react is that it gives you a great declarative interface, but it also provides the component lifecycle methods for times when the declarative API is insufficient and you need an "escape hatch" to imperative programming. The handling of focus is one of these examples. @satya164, the easiest way to handle the " |
@ericvicenti I think those might be useful. since the only thing wrong about them is the names don't match what it does, how about,
|
Also, in addition to these hooks, we can add an HOC |
@satya164 do you have idea when something like this will be implemented? |
@ivpusic feel free to send a PR to implement it |
I think following will be a better API, navigation.addListener('animateIn', doStuff);
navigation.addListener('animateOut', doStuff);
navigation.addListener('focus', doStuff);
navigation.addListener('blur', doStuff); Lifecycle hooks will break when using HOCs and you always need to be the direct child of the navigator to use the lifecycle hooks. Events will work everywhere, even inside the components of |
Unfortunately I think this API won't be very easy to use, because you'll need to re-subscribe every time the navigation prop changes, by listening to lifecycle hooks. Also you'll need to unsubscribe. So I'm afraid the developer experience is worse this way, but I can still be convinced otherwise. Maybe you can post both examples so we can see them side-by-side? I do agree the HOC problem is real, but I think there are ways to work around it. |
I'm not too convinced about the pure listener approach either. I like what @satya164 mentioned before: what if we implement BOTH the good old imperative AND a declarative approach, ie:
This would alleviate the HOC issue raised above, wouldn't it? Not saying this is a great idea, just throwing it in here to get to better solutions. |
I believe there was conversation at some point but is there a potential to just use React lifecycle methods to accomplish all of these vs having to explicitly add this stuff? |
I believe this can be easily solved. it's only a problem if the
It's just a little bit worse because you always have to explicitly un-subscribe. With life-cycle hooks, the developer experience is much worse when you're using HOCs such as Redux's connect. In most of my apps, most of the screens use connect. Though the worse dev experience in events approach is easy to solve using a HOC we'll provide, which manages the subscription under the hood. Personally I think most people should use
We cannot provide a Lifecycle HooksPros
Cons
EventsPros
Cons
|
Hah, clever one @easydaniel :) |
really need a hook~ for us native developers, it is so nature |
@easydaniel Do you have a solution for when the user swipes between tabs like on android ? |
I have
|
@JuniorBoaventura perhaps using redux will be a better solution with binding the nav state and simply do something like
|
@easydaniel Thank you I was thinking about doing something like this but I ended up using react-navigation-is-focused-hoc that works for tap on the tabbar and the slide gesture without any redux implentation. |
@punksta Your workaround is perfectly working, thanks! And sorry to the team, your work is awesome but it's very disappointing that a such component fails to handle basic lifecycle... Sorry for my harsh words, but it should be a basic feature. |
First of all let me just say: It is jaw-dropping that this is not already in react-navigation. Ok, with that out of the way here's my workaround. An example screen: import NavigationStateNotifier from './NavigationStateNotifier'
class MyScreen extends Component {
constructor (props) {
super(props)
this.state = {
// If you'd like to have an `activeScreen` state flag, you can. But you could do anything else you want really!
activeScreen: false
// ...
}
NavigationStateNotifier.newListener(
this,
() => {
this.setState({activeScreen: true})
// anything else that you'd like to do when this screen is navigated to
},
() => {
this.setState({activeScreen: false})
// anything else that you'd like to do when this screen is navigated off of
}
)
}
render () { /* ... */ }
} Here's import NavigationStateNotifier from './app/NavigationStateNotifier'
const AppNavigator = StackNavigator({
Home: { screen: MyScreen },
// and so on...
})
export default class extends React.PureComponent {
render () {
return (
<AppNavigator
onNavigationStateChange={(prevState, currentState) =>
NavigationStateNotifier.onNavigationStateChange(prevState, currentState)}
/>
)
}
} And finally here's the good stuff, 'NavigationStateNotifier.js`: class Listener {
constructor (notifier, key, onNavEnter, onNavExit) {
this.notifier = notifier
this.key = key
this.onNavEnter = onNavEnter
this.onNavExit = onNavExit
}
off () {
this.notifier.removeListener(this)
}
}
class Notifier {
constructor () {
this.listeners = new Set()
}
removeListener (listener) {
this.listeners.delete(listener)
}
onNavigationStateChange (prevState, currState) {
const prevKey = prevState.routes[prevState.index].key
const currKey = currState.routes[currState.index].key
// Handle all exit events...
this.listeners.forEach((listener) => {
if (listener.key === prevKey) {
listener.onNavExit()
}
})
// ...then all enter events
this.listeners.forEach((listener) => {
if (listener.key === currKey) {
listener.onNavEnter()
}
})
}
newListener (screen, onNavEnter, onNavExit) {
const listener = new Listener(
this,
screen.props.navigation.state.key,
onNavEnter,
onNavExit
)
this.listeners.add(listener)
return listener
}
}
export default (new Notifier()) |
Indeed surprising this feature is missing. So basic! Thanks to the team anyway 😄 Here's my solution, I tried keeping it as simple as possible: App.js
Bookmarks.js
Very simple.
|
any update on this ? |
@elyran I'm trying to use your solution I can't find anything with key route name etc this is what I'm getting in action
|
Edited: sorry, too early in the morning I have tried @elyran 's solution and it worked for me with little modifications. I was able to read the route name though not from the action, but from the previous / next state.
|
My solution is bare minimum. It habdles only one type of action. The action
you mention "Navigation/SET_PARAMS" is not the same so I'm not surprised
that the "routeName" is missing.
There's also the back button/nav event which it doesn't handle.
But, it all should be easy to complete. The foundation is layed out.
Shabat Shalom!
On Jan 19, 2018 10:24, "victorbadila" <notifications@github.com> wrote:
I have tried @elyran <https://github.com/elyran> 's solution and it worked
for me. @Gardezi1 <https://github.com/gardezi1> it seems to me you might be
looking at the action and not at the previous/next routes. Could you post
your full code where you hook up to onNavigationStateChange?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#51 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACXAOfThCg3dObIVDvMW_NegsyT0aPsmks5tMFFBgaJpZM4LwTOA>
.
|
I've alot of stack navigators inside a tab navigator. On a particular stack navigator I want such kind of functionality. Yeah I looked into it and found I was looking at the wrong parameter. I had to look at prev and new one. the problem is it is not triggering. Can you look at the code and tell me what is it that I'm doing wrong. I think I'm not attaching the even properly but I can't figure out what is it that I'm doing wrong navigation/index.js
cartScreen/index.js
|
I usually don't pollute threads but in this case, I need to say something :) This thread is bad for everyone - It's the first result from google when searching for focus / react navigation, and in it you mainly get discussion about pros/cons, hacks & patches with a very wide context (using redux or not, using props or not, etc). But no clear choice and resolution from the react-navigation team. Most of it is a discussion on how to implement a fix to the issue and therefore should be taken elsewhere. The actual solutions - cause they exist - are lost in the middle of this mess. They should be catalogued and put in some section of the readme / help - to actually help people & not make them loose hours on this! |
@zeflash is there any for onBlur ?? |
@Gardezi1 no idea - I ended up going the react way. My limited knowledge would tell you that callbacks like this can't properly be achieved via external means and need to be done in the actual code, which isn't done atm. You can always go through the thread to figure it out though ;) |
Hi! After some digging I was told that development of this feature is taking place in this branch https://github.com/react-navigation/react-navigation/tree/%40evv/navigation-events and also was told it has an ETA of several days... Regarding this does @ericvicenti, @skevy or @brentvatne have a more concise ETA for this? Thanks! |
@mgscreativa - a PR for this will be open soon. you can read the RFC for more info: https://github.com/react-navigation/rfcs/blob/master/text/0001-event-system.md closing because we're keeping issues for bugs now and new features belong in either the rfc repo or https://react-navigation.canny.io/feature-requests |
Quick update for everyone, the PR to implement this is now live: #3345 So if you want to review/comment on that implementation, now you can. |
My email inbox is flooded with notifications from this thread. Glad an official feature might finally be on the way. |
In one of my Tabs i need to load Data from the server and do some heavy rendering. I would like to defer that until the Tab is focused in order to improve the JS-Thread performance. How should i implement that?
The text was updated successfully, but these errors were encountered: