导航实验:如何将道具传递给场景?

时间:2016-08-07 03:54:58

标签: navigation react-native

我正在处理数据初始化的应用程序的初始屏幕。

渴望的结果很简单:

  1. 在componentWillMount上加载数据:视图显示loading indicator
  2. 加载数据:视图显示check icon
  3. 1秒后:导航到另一个场景
  4. 为了将视图更改为显示loading indicatorcheck icon,我需要更新传递到初始屏幕场景dataReady道具,但我不知道不知道如何更新导航状态(即通过导航状态的route对象将道具传递给场景)。

    这是我的尝试(不能按预期工作):

    class MainRouter extends React.Component {
    
      componentWillMount() {
        // Load data.
        this.props.initApp();
      }
      componentWillReceiveProps(nextProps) {
        // initAppReady is set to true 1 second after data loaded.
        if (nextProps.initAppReady) {
          this.props.handleNavigation({ type: 'PUSH', route: { key: 'home' } });
        }
      }
    
      renderScene = props => {
        switch (props.scene.key) {
          case 'scene_splash_screen':
            // dataReady is set to true after data loaded.
            return (<SplashScreen dataReady={this.props.dataReady} />);
    
          case 'scene_home':
            return (<Home />);
    
          default:
            return null;
        }
      }
    
      render() {
        return (
          <NavigationCardStack
            direction={'vertical'}
            navigationState={this.props.mainRoutes}
            renderScene={this.renderScene}
          />
        );
      }
    }
    

    因此,更改renderScene时不会调用props.dataReady方法,因此SplashScreen场景不会相应更新。

1 个答案:

答案 0 :(得分:1)

您应该创建一个新的AppLoader组件,该组件显示启动屏幕并执行初始数据加载。此外,您应该让initAppReady函数返回一个承诺,而不是将initApp作为道具传递给路由器,该承诺会在应用准备就绪时解析,然后AppLoader可以执行暂停一秒钟,然后导航到家庭场景。

注意:我注意到你把家庭路线推到了堆栈上。我建议你用归位路线替换堆栈。如果您继续操作,那么用户可能会意外导航回您的启动画面,这可能不是您想要的。

这是我的意思的一个例子:

<强> MainRouter.js

class MainRouter extends React.Component {

  renderScene = props => {
    switch (props.scene.key) {
      case 'scene_splash_screen':
        return (<AppLoader initApp={this.props.initApp} handleNavigation={this.props.handleNavigation} />);

      case 'scene_home':
        return (<Home />);

      default:
        return null;
    }
  }

  render() {
    return (
      <NavigationCardStack
        direction={'vertical'}
        navigationState={this.props.mainRoutes}
        renderScene={this.renderScene}
      />
    );
  }
}

<强> AppLoader.js

const AFTER_INIT_DELAY = 1000;
class AppLoader extends React.Component {

  static propTypes = {
    initApp: PropTypes.func,
    handleNavigation: PropTypes.func,
  };

  constructor(props) {
    super(props);
    this.state = {
      dataReady: false,
    };
  }

  componentWillMount() {
    this.props.initApp()
      .then(() => {
        this.setState({dataReady: true}, this.afterAppInit);
      })
      .catch(() => {
        // Do something if the app init fails
      })
  }

  afterAppInit = () => {
    setTimeout(() => {
      this.props.handleNavigation({ type: 'REPLACE', route: { key: 'home' } });
    }, AFTER_INIT_DELAY);
  }

  render() {
    return (
      <SplashSceen dataReady={this.state.dataReady} />
    );
  }
}