导航实验:如何将道具传递给场景?
Navigation Experimental: How to pass props to scenes?
我正在处理初始化数据的应用程序启动画面。
想要的结果就是:
- 在 componentWillMount 上加载数据:视图显示
loading indicator
- 加载数据时:视图显示
check icon
- 1秒后:导航到另一个场景
为了将显示 loading indicator
的视图更改为 check 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
场景不会相应更新。
您应该创建一个新的 AppLoader
组件,它显示初始屏幕并执行初始数据加载。此外,不是将 initAppReady
作为 prop 传递给路由器,而是应该让 initApp
函数 return 一个承诺,它在应用程序准备就绪时解决,然后 AppLoader
可以做一秒停顿,导航到首页场景。
注意:我注意到您将 home 路线压入堆栈。我建议你用 home route 替换 stack 。如果您继续前进,那么用户可能会不小心导航回您的初始屏幕,这可能不是您想要的。
这是我的意思的一个例子:
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} />
);
}
}
我正在处理初始化数据的应用程序启动画面。
想要的结果就是:
- 在 componentWillMount 上加载数据:视图显示
loading indicator
- 加载数据时:视图显示
check icon
- 1秒后:导航到另一个场景
为了将显示 loading indicator
的视图更改为 check 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
场景不会相应更新。
您应该创建一个新的 AppLoader
组件,它显示初始屏幕并执行初始数据加载。此外,不是将 initAppReady
作为 prop 传递给路由器,而是应该让 initApp
函数 return 一个承诺,它在应用程序准备就绪时解决,然后 AppLoader
可以做一秒停顿,导航到首页场景。
注意:我注意到您将 home 路线压入堆栈。我建议你用 home route 替换 stack 。如果您继续前进,那么用户可能会不小心导航回您的初始屏幕,这可能不是您想要的。
这是我的意思的一个例子:
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} />
);
}
}