-
Notifications
You must be signed in to change notification settings - Fork 16
Add navigation.carefullyGetParent() function #27
Comments
I sympathize with wanting to make it clear what state is for, but I have two problems with this. The state of the route is the most important thing to the route, and it's already pretty verbose to get something like params from it ( My second problem, is that we're bordering on ruining the performance of PureComponent. Previously it wasn't clear to me if In other words, currently in theory if you use PureComponent on a route then However if we add |
To access parent It'll also be nice to have 🤔 |
all good points @dantman. i think @satya164's suggested alternative of making it a function should address most concerns. i'm not sure we want to go as far as enabling the possibility of people traversing their parents -- |
I do think it would be reasonable to give the route access to the navigator's state. But not as a part of props.
Instead since this is state that belongs to the navigator, not to the route, why don't we consider this a type of context rather than a type of prop. And give a context style API to access it. One option which would be familiar to the community would be to add an event to the event emitter. Whenever the state of the navigator changes we'd emit an event and the route could choose to subscribe to that information and only set state based off data they care about. Alternatively, as I kind of prefer, we could treat this similar to actual context. React 16.3 is getting a new context api to replace the old unstable one. They chose to use a render prop for this, because render props are simple and you can also implement HOCs or other APIs using the render prop. So I'd recommend implementing navigator state as a render prop. And then using it to implement a HOC/decorator. <NavigatorState>{(navigatorState) => <RenderSomethingUsingNavigatorState navigatorState={navigatorState}</NavigatorState> Personally I'd turn it into a redux style decorator to map navigator state to data I actually care about. Which would be extremely optimized and automatically re-render whenever state I care about actually changes. @navigatorState((navigatorState, routeState) => ({
isActiveTabNearby: calculateDistanceOfActiveTabFromCurrentTab(navigatorState, routeState.key) < 1,
})
const MyScreen extends PureComponent {
render() {
const {navigation, isActiveTabNearby} = this.props;
const {id} = navigation.state.params;
// ...
}
} My props would not change on every navigate. But Or maybe I'd create an alternative type of optimized render-prop like I created yesterday for a different project. Which would allow re-render to only happen where I actually need it. const MyScreen extends PureComponent {
render() {
const routeState = this.props.navigation.state;
return {
<View>
// ...
<MyNavigatorState
get={navigatorState => navigatorState.index}
render={index => <Text>Current index is: {index}</Text>} />
// ...
</View>
};
} |
Maybe API with context also sounds nice, but it'll probably just be a HOC based API. It's a pain to use the new context API when you need to do stuff outside of render, where I put most of my methods. Keeping that in mind, it doesn't really matter if it's context based or not, since the HOC can be built on top of both. |
@brentvatne I thought that too. But then realized that would only work for a HOC around the route. My later example wouldn't work for a render prop not wrapping the route unless you explicitly passed navigate to it. Because you can only use <MyNavigatorState
navigation={navigation}
get={navigatorState => navigatorState.index}
render={index => <Text>Current index is: {index}</Text>} /> |
@satya164 Where are you suggesting I'm assuming you are thinking of the common pattern. Where you use I just thought I should point out that React is deprecating and removing |
What do you mean by that?
|
discussed further with @ericvicenti and we realized that since we are talking about escape hatches here (the alternative being to create a navigator that exposes the functionality requiring inspecting parent state) we should just expose |
I think people tend to get confused about what
state
refers to on thenavigation
object. For example, when we emit focus and blur events for a tab, people get the state for their route but not the state for the navigator. Usually the state for the route doesn't change. I think there could be many cases where you might want to know the state of the parent navigator. For example, if I'm on tab C and someone just swiped over to tab B, then maybe I want to start fetching data required to render my tab. Another use case came to mind while reading over this: react-navigation/react-navigation#3554. I'd like to be able solve this issue with the following:If we have multiple modal stack navigators, we can just pass that config in and the back button appears wherever expected. It feels like the navigator state is information that we should have access to and I feel a bit handcuffed without it. In the above case I'd have to set the
navigationOptions
on theModalMainScreen
route, and probably would want to be explicit about theinitialRouteName
, which would be workable but I believe not quite as clean or intuitive.We could make this change on master with this code in
createNavigator.js
:I believe we'd need to change some other places for events. But before I embark on a formal RFC for this I wanted to get some thoughts.
The text was updated successfully, but these errors were encountered: