如何在选项卡聚焦事件上调用异步方法?



我正在制作一个应用程序,根据进入时间和退出时间记录保存时间和到期时间。

当前情况:-

  • App.js选项卡导航器选项并将默认选项卡设置为主页
  • Home.jsDues.jsSavings.js分别用于显示选项卡的内容
  • 3个标签:主页,会费和储蓄
  • 主页选项卡:记录进入时间和退出时间
  • 会费选项卡:根据主页选项卡中记录的进入和退出时间显示到期时间
  • 节省
  • 选项卡:根据主页选项卡中记录的进入和退出时间显示节省时间

我面临的问题:-

由于我使用AsyncStorage在 Home 选项卡本身中设置计算到期时间或保存时间的项目,因此我调用函数getDueTime()以在Dues.js中获取compoundDidMount()方法中的项目,但只会工作一次,因为compoundDidMount()方法可以聚焦选项卡,就像在聚焦时初始化选项卡一样, 它将调用compoundDidMount()方法。 但是我想在每次聚焦选项卡时调用函数getDueTime(),以便获得实时计算结果。

我是ReactNative新手,我知道有一种onNavigationStateChange()方法,但我无法使用它。请指导我解决这个问题。

应用.js

import React from 'react'
import {TabNavigator, TabBarTop} from 'react-navigation'
import Home from './tabs/Home'
import Dues from './tabs/Dues'
import Savings from "./tabs/Savings";
export default TabNavigator(
{
Dues: {
screen: Dues,
navigationOptions: {
tabBarLabel: 'Dues',
},
},
Home: {
screen: Home,
navigationOptions: {
tabBarLabel: 'Home',
},
},
Savings: {
screen: Savings,
navigationOptions: {
tabBarLabel: 'Savings',
},
},
},
{
tabBarComponent: TabBarTop,
initialRouteName: 'Home',
tabBarOptions: {
labelStyle: {
fontSize: 23,
},
style: {
backgroundColor: '#4CAF50'
},
indicatorStyle: {
backgroundColor: 'white'
},
inactiveTintColor: '#1A237E',
upperCaseLabel: false
}
}
);

首页.js

import React from 'react'
import {StyleSheet, Text, View, AsyncStorage} from 'react-native'
import {Button} from "../components/Button"
import Moment from 'moment'
export default class Home extends React.Component {
entry = new Moment();
exit = new Moment();
duration = 0;
constructor(props) {
super(props);
this.state = {
curEntryTime: null,
curExitTime: null,
count: 2,
savings: 0,
dues: 0,
btnTitle: 'Office Entry',
visible: true
};
}
onPress = () => {
this.setState({
count: --this.state.count
});
if (this.state.count === 1) {
this.setState({
btnTitle: 'Office Exit',
curEntryTime: Moment().utc().local().format('hh:mm A')
});
this.setEntryTime();
}
else {
this.setState({
btnTitle: ' ',
visible: !this.state.visible,
curExitTime: Moment().utc().local().format('hh:mm A'),
});
this.setExitTime();
}
};
//For Testing
resetData = () => {
AsyncStorage.removeItem('entryTime');
AsyncStorage.removeItem('exitTime');
//AsyncStorage.clear();
};
setEntryTime() {
let obj = {
btnTitleVar: 'Office Exit',
countVar: this.state.count,
curEntryTimeVar: Moment().utc().local().format('hh:mm A')
};
this.entry = Moment(obj.curEntryTimeVar, "hh:mm A");
AsyncStorage.setItem('entryTime', JSON.stringify(obj)).catch((errors) => console.log(errors));
};
setExitTime() {
let obj = {
btnTitleVar: ' ',
countVar: this.state.count,
visibleVar: !this.state.visible,
curExitTimeVar: Moment().utc().local().format('hh:mm A')
};
this.exit = Moment(obj.curExitTimeVar, "hh:mm A");
AsyncStorage.setItem('exitTime', JSON.stringify(obj)).catch((errors) => console.log(errors));
this.duration = Moment.duration(this.exit.diff(this.entry)).asMinutes();
/**
* --------------------------------
* | Logic To Calculate SavedTime |
* |                              |
* |                              |
* |                              |
* --------------------------------
*/
JSON.stringify(savedTime)).catch((errors) => console.log(errors));
}

/**
* --------------------------------
* | Logic To Calculate DueTime   |
* |                              |
* |                              |
* |                              |
* --------------------------------
*/
JSON.stringify(dueTime)).catch((errors) => console.log(errors));
}
};
getEntryTime = async () => {
let entryTime = await AsyncStorage.getItem('entryTime');
let parsedData = JSON.parse(entryTime);
if (parsedData !== null) {
this.setState({btnTitle: parsedData.btnTitleVar});
this.setState({count: parsedData.countVar});
this.setState({curEntryTime: parsedData.curEntryTimeVar});
}
};
getExitTime = async () => {
let exitTime = await AsyncStorage.getItem('exitTime');
let parsedData = JSON.parse(exitTime);
if (parsedData !== null) {
this.setState({btnTitle: parsedData.btnTitleVar});
this.setState({count: parsedData.countVar});
this.setState({visible: parsedData.visibleVar});
this.setState({curExitTime: parsedData.curExitTimeVar});
}
};
getDueTime = async () => {
let dueTime = await AsyncStorage.getItem('dueTime');
let parsedDueTime = JSON.parse(dueTime);
if (parsedDueTime !== null) {
//DueTime state set in Home Tab
this.setState({dues: parsedDueTime.duesVar});
}
};
getSavingTime = async () => {
let savedTime = await AsyncStorage.getItem('savedTime');
let parsedSavedTime = JSON.parse(savedTime);
if (parsedSavedTime !== null) {
//SavedTime state set in Home Tab
this.setState({savings: parsedSavedTime.savingsVar});
}
};
componentDidMount() {
this.getEntryTime().done();
this.getExitTime().done();
this.getDueTime().done();
this.getSavingTime().done();
//alert(this.state.exitTime.diff(this.state.entryTime))
}
render() {
return (
<View style={styles.container}>
<View style={styles.container}>
<View style={[styles.textContainer, {flexDirection: 'row'}]}>
<Text style={[styles.textBody, {color: 'green'}]}>In Time:</Text>
<Text style={[styles.textBody, {color: 'green'}]}>{this.state.curEntryTime}</Text>
</View>
<View style={[styles.textContainer, {flexDirection: 'row'}]}>
<Text style={[styles.textBody, {color: 'red'}]}>Out Time:</Text>
<Text style={[styles.textBody, {color: 'red'}]}>{this.state.curExitTime}</Text>
</View>
</View>
<View style={[styles.container, {flex: 1.5}]}>
<View style={styles.displayButtonContainer}>
{this.state.visible ? <Button sendData={() => this.state.count <= 0 ? null : this.onPress()}
count={this.state.count}
title={this.state.btnTitle}/> : (null,
<Text style={[styles.textBody, {textAlign: 'center', color: '#1A237E'}]}>
{'Swipe Right To See DuesnnSwipe Left to See Savings'}
</Text>)}
</View>
<View style={styles.resetButtonContainer}>
<Button sendData={() => this.resetData()} title={'Reset'}/>
</View>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#81C784'
},
textContainer: {
flex: 1,
justifyContent: 'center',
paddingLeft: 50,
paddingTop: 40,
backgroundColor: 'white'
},
displayButtonContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 50
},
resetButtonContainer: {
justifyContent: 'center',
alignItems: 'center',
},
textBody: {
flex: 1,
fontSize: 25,
fontWeight: '600'
}
});

会费.js

import React from 'react'
import {StyleSheet, Text, View, AsyncStorage} from 'react-native'
import {Button} from "../components/Button"
export default class Dues extends React.Component {
constructor(props) {
super(props);
this.state = {
dueTime: 0
};
}
resetData = () => {
AsyncStorage.removeItem('dueTime');
};
//I want to call this function whenever Dues Tab is focused. 
getDueTime = async () => {
let dueTime = await AsyncStorage.getItem('dueTime');
let parsedDueTime = JSON.parse(dueTime);
if (parsedDueTime !== null) {
this.setState({dueTime: parsedDueTime.duesVar});
}
};
/*This function calls getDueTime only when tab is focused for the first time. After that, I will have to open the app again to see the changed dueTime the next time entry and exit time is recorded*/
componentDidMount() {
this.getDueTime().done()
}
render() {
return (
<View style={styles.container}>
<View style={styles.container}>
<View style={[styles.textContainer, {flexDirection: 'row'}]}>
<Text style={[styles.textBody, {color: 'red'}]}>Current Dues:</Text>
<Text style={[styles.textBody, {color: 'red'}]}>{this.state.dues}</Text>
</View>
</View>
<View style={[styles.container, {flex: 1.5, justifyContent: 'flex-end'}]}>
<View style={styles.resetButtonContainer}>
<Button sendData={() => this.resetData()} title={'Reset'}/>
</View>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#81C784'
},
textContainer: {
flex: 1,
justifyContent: 'center',
paddingLeft: 50,
paddingTop: 40,
backgroundColor: 'white'
},
displayButtonContainer: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
padding: 50
},
resetButtonContainer: {
justifyContent: 'center',
alignItems: 'center',
},
textBody: {
flex: 1,
fontSize: 25,
fontWeight: '600'
}
});

提前谢谢。

你并没有真正澄清为什么你不能使用onNavigationStateChange(),因为你应该完全使用它! :)

我可以提出以下建议: 请改用这样的结构:

AppNavigation - rename App to this
App - imports AppNavigation | root of app and state container
return (
<View>
<AppNavigation
onNavigationStateChange={(prevState, newState) => {
console.log(newState)
/** 
{
"index":0,
"routes":[
{
"type":"Navigation/NAVIGATE",
"routeName":"Home",
"routes":[
{
"key":"Dues",
"routeName":"Dues"
},
{
"key":"Savings",
"routeName":"Savings"
}
],
"index":1,
"key":"id-1521725309375-1"
}
]
}
**/
// important is the "index":1
// it indicates which tab is the currently active one
// in this case you are currently on the 'Savings' Tab
}}
/>
</View>
);

也不要将TabNavigator导出为react-navigation已经使用的TabNavigator。只需称其为AppNavigator/AppNavigation即可。

此外,此结构有助于具有不受屏幕限制的应用范围样式。假设你想要一个顶部标题,指示错误或警告。您现在可以独立于选项卡/屏幕显示。

希望这有帮助

最新更新