atlanteh
atlanteh

Reputation: 5835

react-native-router-flux throws Actions.callback is not defined

Running the following snippet results in the Router throwing

import React from 'react';
import {Scene, Router} from 'react-native-router-flux';

export default App extends React.Component {
  componentDidMount() {
      // This fails
      Actions.login();
  }

  render() {
    return (
      <Router>
        <Scene key="root" hideNavBar>
          <Scene key="login" component={Login} />
          <Scene key="main" component={Main} initial />
        </Scene>
      </Router>
    );
  }
}

The router should have been mounted by the App.componentDidMount, so all the actions are supposed to be working.
If I set timeout for 2 seconds, then it does work. Has anyone ran into it? Am I doing something wrong here?

Upvotes: 2

Views: 1796

Answers (1)

atlanteh
atlanteh

Reputation: 5835

So finally I understood what the problem is.
The problem is not the Scenes taking time to initialize.
Action.login needs to have a the Actions.callback that the Router injects after first actual render which is after the root componentDidMount.

Here's what happens:
Root render function called
Router render function called without state.reducer so does nothing.
Router componentDidMount called - Here the Actions get initialized and the reducer gets saved to the state (setState is async).
Root componentDidMount - here the callback is still not initialized.
Router render called - This call is triggered by the setState before. Now the Actions.callback is injected.

So after second render, the router is initialized.

I managed to find a better solution than an arbitrary setTimeout.
You override the Router render method, and right after it's rendered with data, you notify the parent:

class OverrideRouter extends Router {
    constructor(props) {
        super(props);
        this.render = this.overrideRender;
    }
    overrideRender() {
        const result = super.render();
        if (!result) {
            return result;
        }
        // after first initialization use the regular render.
        this.render = super.render;
        if (this.props.onRouterInitialize) {
            // need this setTimeout to allow this method to complete so that the Actions.callback is populated
            setTimeout(this.props.onRouterInitialize, 10);
        }
        return result;
    }
}

Edit
I managed to fix the problem entirely and sent a pull request to solve it. https://github.com/aksonov/react-native-router-flux/pull/1137

Upvotes: 2

Related Questions