我正在开发移动应用程序,但遇到了我不知道如何解决的问题。
创建屏幕后,我必须从API加载一些数据。我用componentDidMount
的async
方法执行此操作,因此可以使用await
关键字。之后,我要设置状态,以便隐藏Loader组件(只是模式显示文本),并使用API的数据重新渲染屏幕。在Android设备上运行正常。但是,无法在iOS(iPhone X)上运行此代码。调用SomeScreen.js
和Loader.js
的渲染方法,并且Loader.js
渲染方法返回null(已通过控制台检查),但iPhone上的视图未更新。加载程序模式仍然存在,即使其渲染方法返回null也不例外。我做错什么了吗?调用this.foceUpdate()
也无济于事。
SomeScreen.js
import React, {Component} from 'react';
import Loader from 'components/Loader/Loader';
export default class SomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
data: []
};
}
async componentDidMount() {
const data = await this.loadData();
this.setState({loading: false, data: data})
}
async loadData() {
//fetch and return data from API
}
render() {
return (
<SafeAreaView style={{flex: 1}}>
<Loader loading={this.state.loading}/>
//other rendering...
</SafeAreaView>
);
}
}
Loader.js
import React, {Component} from 'react';
import {Modal, Text, View} from 'react-native';
export default class Loader extends Component {
static defaultProps = {
loading: false
};
render() {
if (this.props.loading !== true) {
return null;
}
return(
<Modal
transparent={false}
animationType={'none'}
visible={true}>
<View style={{backgroundColor: "white", flex: 1, justifyContent: "center"}}>
<Text>Loading data...</Text>
</View>
</Modal>
)
}
}
我不确定为什么您会看到iOS和Android之间的差异,但是我认为您可以尝试简化Loader
组件的渲染方法。这样,您将避免使用2个return
调用。
import React, {Component, Fragment} from 'react';
render() {
return (
<Fragment>
{this.props.loading ? null : {
<Modal
transparent={false}
animationType={'none'}
visible={this.props.loading}>
<View style={{backgroundColor: "white", flex: 1, justifyContent: "center"}}>
<Text>Loading data...</Text>
</View>
</Modal>
}
</Fragment>
)
}
上面的代码检查loading
属性并加载Modal
组件,否则为空。我还将this.props.loading
属性作为值添加到模态的visible
属性。我认为可能已经丢失了。
嗯,终于找到答案了。这是因为即使将animationType
设置为none
,iOS上的模态上也有打开动画。而且,如果我将loading
更改为false
,则在捕获此动画之前,仍将打开模态。动画大约需要550毫秒,而我的API调用大约需要200毫秒。
Loader.js
import React, {Component} from 'react';
import {Modal, Text, View} from 'react-native';
export default class Loader extends Component {
static defaultProps = {
loading: false
};
constructor(props) {
super(props);
this.state = {
loading: props.loading
};
}
componentWillReceiveProps(nextProps, nextContext) {
if (this.state.loading === true && nextProps.loading === false) {
setTimeout(() => {
this.setState({loading: false});
}, 600);
}
if (this.state.loading === false && nextProps.loading === true) {
this.setState({loading: true});
}
}
render() {
if (this.state.loading !== true) {
return null;
}
return(
<Modal
transparent={false}
animationType={'none'}
visible={this.state.loading}>
<View style={{backgroundColor: "white", flex: 1, justifyContent: "center"}}>
<Text>Loading data...</Text>
</View>
</Modal>
)
}
}
基本上,在我的解决方案中,我确保模态以600毫秒的延迟关闭,因此它有时间完成其弹出动画。