aksonov / react-native-router-flux

The first declarative React Native router
MIT License
8.98k stars 2.11k forks source link

Actions.SCENE doing nothing #1102

Closed fmmajd closed 7 years ago

fmmajd commented 8 years ago

hi I'm adding a simple login screen to my app, but I'm not able to call Actions.home once the user is authenticated. I have a button that when pressed, calls a function to connect to the server and get auth status, and when successful, I call Actions.home. but nothing happens. no error or warning. just nothing. I have tried all forms of it, Actions.home, Actions.home(), {Actions.home}, saving Actions.home as state in the constructor and then using state, ... nothing worked. but in my other screens when I call Actions.somewhere in onPress props it works. I read most of the issues here, and questions on StackOverflow(there weren't a lot), but couldn't understand what's wrong. I used all the solutions suggested everywhere, but nothing.

when I console.log(Actions.home), it's what I see: image

when I console.log(Actions.home()), it says undefined.

Steps to reproduce

  1. initial project, add router and redux-react libraries

2.add router definition

3.add login screen and other functions

code for router.js:

<Scene key="root">
        <Scene key="login" title="login"  component={Login} hideTabBar hideNavBar initial />
        <Scene key="tabsRoot" tabs tabBarStyle={[styles.tabBar, styles.tabBarShadow]} >
            <Scene key="tab_home" iconName="home" icon={TabBarItem} >
                <Scene key="home" title="saba" component={Home} navBar={NavBar} />
                <Scene key="campaignHome" title="campaign" hideTabBar component={Campaign} navBar={NavBar} direction="vertical" />
            </Scene>
            ......
        </Scene>
</Scene>

code for login screen component used in router:

export default class Login extends Component{
     constructor(props){
        super(props);
        this.state = {
            name: '',
            phone: '',
            shouldLogin: false,
            shouldRegister: false,
            error: false,
        };
        this._checkAuth = this._checkAuth.bind(this);
        this._onNumberChanged = this._onNumberChanged.bind(this);
        this._isRegistered = this._isRegistered.bind(this);
        this._isNotRegistered = this._isNotRegistered.bind(this);
    }

    async _isRegistered(response){
        var user = response.payload.user;
        this.state = {
            name: user.name,
            phone: user.phone,
            shouldLogin: true,
        };

        Actions.home;
    }

    _isNotRegistered(response){
        var error = response.error;
        if(!error.code === NOT_REGISTERED_CODE){
            this.setState({
                shouldLogin: false,
                shouldRegister: false,
                error: true,
            })
            throw new AuthException("server responded with unrecognised object");
        }

        this.setState({
            shouldLogin: false,
            shouldRegister: true,
            error: false,
        })
    }

    _checkAuth(){

        var { phone } = this.state;

        var data = {
            phone: phone,
        }

        let url = buildQuery(AuthTypes.LOGIN, data);

        console.log("usl: " + url);

        //connect to server
       ....
            if(response.success){
                this._isRegistered(response);
            }
            else{
                this._isNotRegistered(response);
            }
    }

    _onNumberChanged(event){
        var phone = event.nativeEvent.text;
        this.setState({
            phone: phone,
        });
    }

    render(){
        return(
            <View style={[styles.container]}>
                <View style={[styles.imgContainer]}>
                    <Image source = { require('./../Images/login.png')} width="200" height="200" />
                </View>
                <View style={[styles.form]}>
                    <View style={[styles.inputContainer]}>
                        <TextInput style={[styles.input]} placeholder="enter your phone number" onChange={ this._onNumberChanged } maxLength={12} />
                    </View>
                    <TouchableWithoutFeedback onPress={ this._checkAuth } >
                        <View style={[styles.submitContainer]}>
                            <View>
                                <Text style={[styles.text, styles.loginButton]}>login</Text>
                            </View>
                        </View>
                    </TouchableWithoutFeedback>
                </View>
            </View>
        )
    }
}
zianwar commented 8 years ago

I have exactly the same issue,

Actions.NAME is not working, and when I console log Actions.NAME() it prints undefined.

"react": "^15.2.1",
"react-native": "^0.31.0",
"react-native-router-flux": "^3.35.0",
fmmajd commented 8 years ago

so I found the solution, and apparently, we can Actions.go to scenes that are not the current scene's sibling. so in my case, I have to use Actions.tabsRoot. is there a workaround? is it gonna be added? I think lots of people would appreciate if it was added. tnx

zianwar commented 8 years ago

@fmmajd I solved this issue by dispatching the Action.NAME from the store rather than invoking it with Actions.NAME()

Try this:

dispatch(Actions.NAME)
lynndylanhurley commented 8 years ago

I'm having the same issue.

@Zianwar - that didn't help in my case.

@fmmajd - can you show exactly what you did to get past this?

fmmajd commented 8 years ago

@Zianwar I actually don't want to complicate my app by adding reducer to routes.

@lynndylanhurley you can't use Actions.SCENE_KEY to go to a scene that is not current scene's sibling. the two scenes should have the same parent. so in my case, I can't use Actions.home, but I can use Actions.tabsRoot

juanpasolano commented 8 years ago

I checked and there is no Actions.go I'm trying to get to a nested scene inside a drawer

<Scene key="root" hideNavBar={true}>
    <Scene key="drawer" component={Drawer} open={false}>
        <Scene key="profile" component={Profile} title="Profile"/>
        <Scene key="workspace" component={Workspace} initial={true}/>
    </Scene>
    <Scene key="login" component={Login} initial={true} type={ActionConst.REPLACE}/>
</Scene>

i'm trying to get from the loginto the Actions.workspace(), which it doesn't work I have to use Actions.drawer() (as @fmmajd mentions) and since workspace is the intial it works. However then from the drawer I want to go to Actions.profile() and the only thing that works is Actions.profile({type: 'replace'}) which is not desired since I want to go back.

@fmmajd I did not understand how you solved it!

fmmajd commented 8 years ago

@juanpasolano in your case, I do not know. I just needed one scene and thus I made it initial.

but something I can think of for your problem, is that you add a scene in drawers, make it initial, and based on props decide which scene to go.

like:

<Scene key="decide" component={Decide} title="goSomewhere"/>

and then in Decide component constructor:

let target = this.props.destination;
if(target === 'profile')
  Actions.profile({type:'replace');
else if(target === 'workspace')
  Actions.workspace({type:'replace');

and finally, when in other components you wanna come to drawers scenes:

Actions.drawer({destination: 'profile');
Actions.drawer({destination: 'workspace');

this is not the perfect solution, it's just a workaround, but it should work.

tukunangonehub commented 7 years ago

any update for this issue?