我正在制作一个应用程序,根据输入时间和退出时间记录保存时间和截止时间。
目前的情况: -
App.js
用于TabNavigator选项并将默认选项卡设置为HomeHome.js
,Dues.js
和Savings.js
分别用于显示标签的内容我面临的问题: -
由于我使用AsyncStorage
在Home选项卡本身中设置计算到期时间或节省时间的项目,我调用函数getDueTime()
来获取compoundDidMount()
中的Dues.js
方法中的项目,但是只有一次因为compoundDidMount()
方法工作于聚焦选项卡就像标签在聚焦时被初始化,它将调用compoundDidMount()
方法。但是每次选项卡聚焦时我想调用函数getDueTime()
,这样我就能得到实时计算结果。
我是ReactNative
的新手,我知道有一种onNavigationStateChange()
方法,但我无法使用它。请指导我解决这个问题。
App.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
}
}
);
Home.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 Dues\n\nSwipe 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'
}
});
Dues.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
导出为TabNavigator
已经使用过的react-navigation
。只需称它为AppNavigator
/ AppNavigation
。
此外,此结构有助于拥有不受屏幕限制的应用程序范围样式。想象一下,你想要一个顶部标题,表示错误或警告。您现在可以独立显示选项卡/屏幕。
希望这可以帮助