Reverse order of JavaScript code - react native - javascript

I am trying to count the number of times a button is pressed within a second.
It's working, for the most part, it tracks it and outputs it.
But the problem is that it outputs the button press count from the last second instead of the current second.
I think it would work if the order was reversed somehow, how do I fix up this function? Thanks.
const [clicksPerSecond, setClicksPerSecond] = useState(0);
const [tempCounter, setTempCounter] = useState(0);
const [tempCounter2, setTempCounter2] = useState(0);
const { setCounter, counter } = useContext(CountContext);
useEffect(() => {
console.log(tempCounter);
if (tempCounter != 0) {
if (tempCounter == 1) {
setTimeout(() => {
setClicksPerSecond(tempCounter2);
setClicksPerMinute(tempCounter2 * 60);
setTempCounter(1);
console.log('Clicks per second final: ' + tempCounter2);
}, 1000)
} else {
setTempCounter2(tempCounter);
console.log('Clicks per second: ' + tempCounter);
}
}
setTempCounter(tempCounter + 1);
}, [counter])
return (
<View style={[styles.container, { backgroundColor: colors.background }]}>
<View elevation={7.5} style={{ backgroundColor: colors.background, borderRadius: 500 }}>
<TouchableOpacity
onPress={() => setCounter(counter + 1)}
style={[styles.counterButton, { backgroundColor: colors.primary, borderColor: colors.container, borderWidth: 0 }]}>
<Text></Text>
<Text style={{ fontSize: 60 }}>{counter}</Text>
<Text>{clicksPerSecond} CPS</Text>
</TouchableOpacity>
</View>
</View>
);
}

You can instead just increment the count and decrement it after a second.
export default function App() {
const [clicks, setClicks] = React.useState(0);
const onClick = () => {
setClicks((c) => c + 1);
setTimeout(() => setClicks((c) => c - 1), 1000);
};
return (
<div>
<button onClick={onClick}>Click me</button>
<p>Clicked {clicks} times</p>
</div>
);
}
You will also need to track if the component is unmounted before decrement, which I think you can do using refs. Example

Related

How to make a variable change every time i insert a coin to reach a certain value?

So i have a coin box that collects coins and it recognize their value.
I want to make the user be able to insert coin and pay a service that costs 2.0 €.
The user can pay with coins from 2.0 € , 1.0 € , 0,50 € , 0,20 € , 0,10 €.
In my react-native now i created a function where if the coin reaches 2 euros the coin box stops (listener).
But how can i sum every time the user insert different coins of different values?
here is my code:
import {useNavigation} from '#react-navigation/native';
import React, {useEffect, useState} from 'react';
import {
Alert,
DeviceEventEmitter,
NativeEventEmitter,
NativeModules,
Pressable,
StyleSheet,
Text,
View,
} from 'react-native';
const {CoinBoxCollector} = NativeModules;
export default function HomeScreen() {
const [off, setOff] = useState(true);
const navigation = useNavigation();
let coinInserted = 0;
const coinValueStartExperience = 2;
let totalCoin;
async function onCoinDetected(coin: any) {
if (coinInserted >= coinValueStartExperience) {
//navigation.navigate('VideoScreen');
console.log("hai pagato per l' esperienza");
return await CoinBoxCollector.stop();
}
if (coinInserted !== 0 || coinInserted < coinValueStartExperience) {
console.log('DEVI INSERIRE ALTRI SOLDI');
totalCoin = coinInserted + parseFloat(coin);
// console.log('ricevuti ' + totalCoin + ' €');
}
// Alert.alert('ricevuti soldi', coin);
}
const pressInit = async () => {
// setOff(false);
return await CoinBoxCollector.initialize();
};
const pressStop = async () => {
// setOff(false);
console.log('getttoniera stoppata');
return await CoinBoxCollector.stop();
};
useEffect(() => {
const eventEmitter = new NativeEventEmitter(NativeModules.CoinBoxCollector);
const eventListener = eventEmitter.addListener(
'onReceivedCoin',
onCoinDetected,
);
// return eventListener.remove();
}, []);
return (
<View style={styles.container}>
<Pressable style={styles.btn} onPress={pressInit}>
<Text style={styles.btnText}>Initialize</Text>
</Pressable>
<Pressable style={styles.btn} onPress={pressStop}>
<Text style={styles.btnText}>Stop it</Text>
</Pressable>
{/* <Pressable
style={styles.btn}
onPress={() => navigation.navigate('VideoScreen')}>
<Text style={styles.btnText}>navigate</Text>
</Pressable> */}
{/* {!off && (
<View>
<Text>Bravo hai Pagato !</Text>
</View>
)} */}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignContent: 'center',
},
btn: {
marginTop: 30,
backgroundColor: '#841584',
width: '5%',
height: 30,
marginLeft: '48%',
},
btnText: {
color: 'white',
textAlign: 'center',
},
});
thank you in advance for the answer
If I understand correctly what you want, you're going to need to use useState for this.
const [totalInserted, setTotalInserted] = useState(0);
// and then every time a coin is inserted you'd do
setTotalInserted((prev) => prev+amountInserted);
// you can get what as been inserted so far by looking at totalInserted

Can setInterval block user input?

I tried to program a little stopwatch to test something out but after clicking "Start" and its running the "Stop", "Lap" and "Reset" Buttons register the input up to a second or more after I click them. What am I missing here?
My guess is it has something to do with the useEffect hook, but Im not sure since I haven't used React or React Native that extensively.
export default function TabOneScreen({ navigation }: RootTabScreenProps<'TabOne'>) {
const [time, setTime] = useState<number>(0);
const [timerOn, setTimerOn] = useState(false);
const [lapCounter, setLapCounter] = useState<number>(0);
const [laps, setLaps] = useState<{count: number, lapTime: number}[]>([])
useEffect(() => {
var interval: any = null;
if (timerOn) {
interval = setInterval(() => {
setTime((prevTime) => prevTime + 10);
}, 10);
} else if (!timerOn) {
clearInterval(interval);
}
return () => clearInterval(interval);
}, [timerOn]);
return (
<View style={styles.container}>
<Text>time:</Text>
<View style={styles.timer}>
<Text>{("0" + Math.floor(time / 60000) % 60).slice(-2)}:</Text>
<Text>{("0" + Math.floor(time / 1000) % 60).slice(-2)}:</Text>
<Text>{("0" + (time / 10) % 100).slice(-2)}</Text>
</View>
<View style={styles.buttons}>
<Button
title="Start"
onPress={() => setTimerOn(true)}
/>
<Button
title="Stop"
onPress={() => setTimerOn(false)}
/>
<Button
title="Lap"
onPress={() => {
setLapCounter(counter => counter += 1)
setLaps(prevLaps => [
...prevLaps,
{count: lapCounter, lapTime: time}
]
)
}}
/>
<Button
title="Reset"
onPress={() => {
setTimerOn(false)
setTime(0)
setLapCounter(0)
setLaps([])
}
}
/>
</View>
<FlatList
data={laps}
renderItem={({ item }) =>
<View style={styles.lapList}>
<Text style={styles.item}>Lap: {item.count}</Text>
<Text style={styles.item}>{item.lapTime}</Text>
</View>
}
/>
</View>
);
}
On the "else if" you clear an empty interval (because you did not save the previous one anywhere). Create a new hook, such as useTimer.
Or use a premade like: https://www.npmjs.com/package/use-timer

React Native not displaying correct image

I'm trying to make a slideshow where the user can play them in a default or random order and cycle through them by pressing a button. The problem comes when the user has chosen random mode; pressing the button still increments the currentIndex variable, but for some reason images[currentIndex] does not change.
const SlideshowScreen = (props) => {
const settings = props.route.params.settings;
const [images, setImages] = useState(settings.random ? props.route.params.images.sort((a, b) => 0.5 - Math.random()) : props.route.params.images);
const [currentIndex, setCurrentIndex] = useState(0);
useEffect(() => {
console.log('currentIndex', currentIndex, images[currentIndex]);
}, [currentIndex])
const newImage = () => {
if (currentIndex + 1 >= images.length) {
console.log('done');
}
else {
setCurrentIndex(currentIndex + 1);
}
}
return (
<View style={styles.mainContainer}>
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={images[currentIndex].path} key={images[currentIndex].id} />
</View>
<TouchableOpacity onPress={() => newImage()}>
<Text>Next image</Text>
</TouchableOpacity>
</View>
)
}
On some clicks of the button this happens, and on others it doesn't. How is this happening? Any help would be great, thanks.

How to track how longer user is on app for react native

I am trying to count in minutes and hours how longer a user is on the app for and display it. I have got the app counting minutes I just cant seem to work out how to track when the app is active or not. Theres documentation on appState but I cannot figure out how to incorporate this into counting. Here is my code:
function Overview() {
const appState = useRef(AppState.currentState);
const [appStateVisible, setAppStateVisible] = useState(appState.current);
const [count, setCount] = useState(0);
const [active, setActive] = useState(false);
useEffect(() => {
const subscription = AppState.addEventListener("change", nextAppState => {
if (appState.current.match(/inactive|background/) && nextAppState === "active") {
setActive(true);
}
appState.current = nextAppState;
setAppStateVisible(appState.current);
console.log("AppState", appState.current);
});
return () => {
subscription.remove();
};
}, []);
useEffect(() => {
const id = setInterval(() => setCount((oldCount) => oldCount + 1), 1000);
return () => {
clearInterval(id);
};
}, []);
return (
<View style={{margin: 32}}>
<View style={{marginBottom: 32}}>
<Text style={{fontSize: 36, fontFamily: 'Roboto_400Regular'}}>Great!</Text>
<Text style={{fontSize: 16, color: '#878787', fontFamily: 'Roboto_400Regular'}}>Average mood 23%</Text>
</View>
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<OverviewContainer title="Weather" value="14 C" />
<OverviewContainer title="Time on app" value={`${(count/60).toFixed(0).toString()} mins`} />
</View>
</View>
);
}
Any help on putting the two together be great, thanks :)
You can access the current appstate as well. How about something like
setCount(if AppState.currentState is active then add one)

Set an expiration date using Use effect React Native, but screen does not re-render properly

I am working on an app where I need to filter by dates to show on a particular screen. The idea is anything within 30 days of today's date should be populated in the filter. I am trying to get that screen to render as soon as the app is opened but it only renders after playing around on other screens.
Here is the logic below. Any help is appreciated.
const ExpiringCertificationsScreen = () => {
const { state, fetchCertifications } = useContext(CertificationContext);
const [expiration, setExpiration] = useState([]);
const diffDays = date => {
let today = new Date(Date.now()).toLocaleDateString();
let expire = new Date(date.toLocaleDateString());
let difference = new Date(expire).getTime() - new Date(today).getTime();
return difference / (1000 * 3600 * 24);
};
const filterExpirationDate = state.filter(item => {
return diffDays(new Date(item.expirationDate)) <= 30;
});
useEffect(() => {
if (filterExpirationDate.length > 0) {
console.log(filterExpirationDate);
setExpiration(filterExpirationDate);
} else {
console.log('Down');
}
}, []);
if (expiration.length === 0) {
return (
<Body>
<Text style={styles.title}>EXPIRING SOON</Text>
<Text style={{ margin: 15 }}>
There aren't any certifications expiring soon
</Text>
</Body>
);
}
return (
<Body>
<Text style={styles.title}>EXPIRING SOON</Text>
<ScrollView style={{ marginTop: 15 }}>
<FlatList
data={expiration}
keyExtractor={item => item._id}
renderItem={({ item }) => {
return (
<Certifications
title={item.title}
month={item.expirationDate}
description={item.description}
id={item._id}
/>
);
}}
/>
</ScrollView>
</Body>
);
};
I have updated your code as per your requirement.. Please check and acknowledge
const ExpiringCertificationsScreen = () => {
const { state, fetchCertifications } = useContext(CertificationContext);
const [expiration, setExpiration] = useState([]);
const diffDays = date => {
let today = new Date(Date.now()).toLocaleDateString();
let expire = new Date(date.toLocaleDateString());
let difference = new Date(expire).getTime() - new Date(today).getTime();
return difference / (1000 * 3600 * 24);
};
useEffect(() => {
const filterExpirationDate = state.filter(item => {
return diffDays(new Date(item.expirationDate)) <= 30;
});
console.log(filterExpirationDate);
setExpiration(filterExpirationDate);
}, [state]);
return expiration.length === 0 ? (
<Body>
<Text style={styles.title}>EXPIRING SOON</Text>
<Text style={{ margin: 15 }}>
There aren't any certifications expiring soon
</Text>
</Body>
) :(
<Body>
<Text style={styles.title}>EXPIRING SOON</Text>
<ScrollView style={{ marginTop: 15 }}>
<FlatList
data={expiration}
keyExtractor={item => item._id}
renderItem={({ item }) => {
return (
<Certifications
title={item.title}
month={item.expirationDate}
description={item.description}
id={item._id}
/>
);
}}
/>
</ScrollView>
</Body>
);
};

Categories

Resources