Skip to content
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

View not responding after custom getStateForAction #2495

Closed
vanBrunneren opened this issue Aug 30, 2017 · 4 comments
Closed

View not responding after custom getStateForAction #2495

vanBrunneren opened this issue Aug 30, 2017 · 4 comments

Comments

@vanBrunneren
Copy link

Current Behavior

I have a StackNavigator with several routes inside. I have a DrawerLayout on the left side. When I press on a link in the drawer I want to open that route and if it was already opened before I want to "switch" to this route and not doing a "goBack" nor a "Push". I want to do this because I don't want a rerender when I show a view which is already opened

I realized this with overwriting getStateForAction and check if my route is already in the stack.

const defaultGetStateForAction = CPlusNavigator.router.getStateForAction;
CPlusNavigator.router.getStateForAction = (action, state) => {
    routes = state.routes;
			
    let index = routes.findIndex((item) => {
        return item.routeName === action.routeName;
    });
					
    if(index !== -1) {

	return {
	    index,
	    routes
	}

    }
    return defaultGetStateForAction(action, state);

}  

This is working and it shows the route (screen) which I have selected in the Drawer. But the Screen is now not more responding to any interaction (onPress, Scroll or whatever). This happens on every device an simulator I have tested it on.

Problem .gif

Expected Behavior

When I'm trying the "same thing" just with the goBack() function it works as it should. So my expected behavior is that my Screen is available after the my custom getStateForAction function. Here a .gif how it works with the BackButton
BackButton

Is there a way to debug this? I'm stucked as soon as I cannot press on anything.
Just a guess, is react-navigation somewhere checking the length of routes? Because usually the index has the same size as the routes but in my case this is not true. Is this maybe a bad solution and anyone has a better case for this? I searched for cases like this on several places but it seems I'm the only one who wants to do this. Is there a better/implemented way to do this or is this just a bad behavior we should avoid?

Your Environment

software version
react-navigation 1.0.0-beta.12
react-native 0.47.2
node 8.0.0
npm or yarn yarn 0.24.6
@spencercarli
Copy link
Member

Could you put together a small demo of this issue? Thanks!

@vanBrunneren
Copy link
Author

Thank you for your help. Here is a minimal example, I didn't get it running with expo or something but you can just copy this file, install react-navigation and it should run:

import React, { Component } from 'react';

import {
	View,
	Text,
	DrawerLayoutAndroid,
	AppRegistry
} from 'react-native';

import {
	StackNavigator,
	NavigationActions
} from 'react-navigation';

class FirstRoute extends Component {

	render() {
		return(
			<View>
				<Text onPress={ () => console.log("firstRoute") }>FirstRoute</Text>
			</View>
		);
	}

}

class SecondRoute extends Component {

	render() {
		return(
			<View>
				<Text onPress={ () => console.log("secondRoute")}>SecondRoute</Text>
			</View>
		);
	}

}

class DrawerView extends Component {

	render() {

		return(
			<View>
				<Text onPress={ () => this.props.navigator.dispatch(NavigationActions.navigate({routeName: 'firstRoute'})) }>Route 1</Text>
				<Text onPress={ () => this.props.navigator.dispatch(NavigationActions.navigate({routeName: 'secondRoute'})) }>Route 2</Text>
			</View>
		);
	}

}

class DrawerNavigatorContainer extends Component {

	constructor() {
		super();

		this.state = {
			CustomNavigator: View,
			isLoading: true
		}

	}

	componentDidMount() {

		const myRoutes = [];

		myRoutes['firstRoute'] = {
			screen: FirstRoute
		};

		myRoutes['secondRoute'] = {
			screen: SecondRoute
		};

		const CustomNavigator = StackNavigator(myRoutes);
		const defaultGetStateForAction = CustomNavigator.router.getStateForAction;
		CustomNavigator.router.getStateForAction = (action, state) => {

			let routes;
			if(state && state.routes) {

				routes = state.routes;
					
				let index = routes.findIndex((item) => {
					return item.routeName === action.routeName;
				});
				
				if(index !== -1) {

					return {
						index,
						routes
					}

				}

			}

			return defaultGetStateForAction(action, state);

		}

		this.setState({CustomNavigator: CustomNavigator, isLoading: false});

	}

	render() {

		if(this.state.isLoading) {
			return <View />;
		}

		return(
			<DrawerLayoutAndroid
				ref={'ROOT_DRAWER'}
				drawerWidth={300}
				drawerPosition={DrawerLayoutAndroid.positions.Left}
				renderNavigationView={() => <DrawerView navigator={this.refs.NAVIGATOR} />}>
				<this.state.CustomNavigator screenProps={this} ref={'NAVIGATOR'} />
			</DrawerLayoutAndroid>
		);

	}

}

class DrawerNavigator extends Component {

	render() {

		return <DrawerNavigatorContainer />;
	
	}

}


AppRegistry.registerComponent('DrawerIssue', () => DrawerNavigator);

In this minimal example it's just with two routes and a Text with an onPress which fires a console.log.
As you can seen in this .gif when you navigate from the first to the second and then back to the first (with my custom getStateForAction, not with goBack()) the onPress method is not firing. The same is with ScrollView and any other component, so you can say the screen is not responding.

Problem .gif

Is there a way to debug this?

@vanBrunneren
Copy link
Author

@spencercarli where you able to track down my issue or do you require more information?

@afshin-hoseini
Copy link

afshin-hoseini commented Apr 8, 2018

For anyone else who encounter this problem. I faced this issue and after spending a lot of time and searches found that, I mistakenly remove all callback listeners from EventEmitter somewhere in component's lifecycle.

EventEmiter.removeAllListeners()

Check if this is your case or not..!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants
@brentvatne @spencercarli @vanBrunneren @afshin-hoseini @kelset and others