'Resetting internal values of custom components
Just started learning React Native, starting by building a basic egg timer app.
I'm using a custom RadioButton component, but having trouble resetting the value's for these once the timer is reset.
How do I reset the internal values (userOption) of the Radio Button, when the timer runs it's onExpire() method?
What's the best way to go about this? Do I need to restructure my code?
TIA
RadioButton Component
import React, { useState } from 'react';
import { View, Text, Pressable } from 'react-native';
import styles from './styles';
export default function RadioButton({ data, onSelect }) {
const [userOption, setUserOption] = useState(null);
const selectHandler = (value) => {
onSelect(value);
setUserOption(value);
};
return (
<View style={{flexDirection: "row"}}>
{data.map((item) => {
return (
<Pressable value={item.value} key={item.key} style={
[ (item.value === userOption ? styles.selected : styles.unselected),styles.baseStyles]
}
onPress={() => selectHandler(item.value)}
>
<Text style={styles.controlText}>{item.value}</Text>
</Pressable>
);
})}
</View>
);
}
Main App Code (excluding css)
import React, { useState, useRef, useEffect } from 'react';
import { StyleSheet, Text, View, SafeAreaView, TouchableHighlight, useWindowDimensions, StatusBar, Modal, ScrollView } from 'react-native';
import { useFonts} from '@expo-google-fonts/inter';
import { useTimer } from 'react-timer-hook';
import { AntDesign, Foundation } from '@expo/vector-icons';
import { Audio, Video } from 'expo-av';
import { SliderPicker } from 'react-native-slider-picker';
import { Slider, Box , NativeBaseProvider, extendTheme, Radio, Button,Pressable } from 'native-base';
//import EZSlider from './EZSlider.js';
import RadioButton from './RadioButton';
export default function App() {
const window = useWindowDimensions();
const [loaded] = useFonts({
/*Dont use dash in name */
DSDigital : require('./assets/fonts/DSDigital.ttf'),
LatoReg : require('./assets/fonts/Lato-Regular.ttf'),
});
function MyTimer({ expiryTimestamp }) {
const bgcolour = '#fef8ea';
const buttonColor = '#023e8a';
//color canvas
//egg black 181304
const [sound, setSound] = React.useState();
async function playSound() {
console.log('Loading Sound');
const { sound } = await Audio.Sound.createAsync(
require('./assets/alarm1.mp3')
);
setSound(sound);
console.log('Playing Sound');
await sound.playAsync(); }
React.useEffect(() => {
return sound
? () => {
console.log('Unloading Sound');
sound.unloadAsync(); }
: undefined;
}, [sound]);
const {
seconds,
minutes,
hours,
days,
isRunning,
start,
pause,
resume,
restart,
} = useTimer({ expiryTimestamp, autoStart: false, onExpire: () => {
//TO DO - check if stop or play button was pressed - exit
if(!userCancelled){
setModalVisible(!modalVisible);
console.log('timer expired') ;
playSound();
}
setDoneness(null);
setEggSize(null);
setTemp(null);
/*******RESET RADIO BUTTONS HERE***********/
}});
//initialTime: 220,
const [modalVisible, setModalVisible] = useState(false);
const buttonActiveOpacity = 0.9;
const buttonUnderlayColor = '#bed9f9';
//const [value, setValue] = React.useState('one');
const [state, setState] = React.useState(false);
const toggleState = () => {
setState(!state);
console.log('toggle State ran');
};
var time = new Date();
const timer_presets = [
{ key: '1', doneness: 'Soft', egg_size: 'S', temp:'Room Temp', time:'0:05' /*'3:10' */ },
{ key: '2', doneness: 'Soft', egg_size: 'M', temp:'Room Temp', time:'3:40' },
{ key: '3', doneness: 'Soft', egg_size: 'L', temp:'Room Temp', time:'4:10' },
{ key: '4', doneness: 'Soft', egg_size: 'XL', temp:'Room Temp', time:'4:30' },
{ key: '5', doneness: 'Medium', egg_size: 'S', temp:'Room Temp', time:'4:10' },
{ key: '6', doneness: 'Medium', egg_size: 'M', temp:'Room Temp', time:'4:40' },
{ key: '7', doneness: 'Medium', egg_size: 'L', temp:'Room Temp', time:'5:10' },
{ key: '8', doneness: 'Medium', egg_size: 'XL', temp:'Room Temp', time:'5:40' },
{ key: '9', doneness: 'Hard', egg_size: 'S', temp:'Room Temp', time:'8:00' },
{ key: '10', doneness: 'Hard', egg_size: 'M', temp:'Room Temp', time:'8:40' },
{ key: '11', doneness: 'Hard', egg_size: 'L', temp:'Room Temp', time:'9:30' },
{ key: '12', doneness: 'Hard', egg_size: 'XL', temp:'Room Temp', time:'10:20' },
{ key: '13', doneness: 'Soft', egg_size: 'S', temp:'Fridge', time:'4:00' },
{ key: '14', doneness: 'Soft', egg_size: 'M', temp:'Fridge', time:'4:40' },
{ key: '15', doneness: 'Soft', egg_size: 'L', temp:'Fridge', time:'5:20' },
{ key: '16', doneness: 'Soft', egg_size: 'XL', temp:'Fridge', time:'5:40' },
{ key: '17', doneness: 'Medium', egg_size: 'S', temp:'Fridge', time:'5:00' },
{ key: '18', doneness: 'Medium', egg_size: 'M', temp:'Fridge', time:'5:40' },
{ key: '19', doneness: 'Medium', egg_size: 'L', temp:'Fridge', time:'6:20' },
{ key: '20', doneness: 'Medium', egg_size: 'XL', temp:'Fridge', time:'6:50' },
{ key: '21', doneness: 'Hard', egg_size: 'S', temp:'Fridge', time:'8:50' },
{ key: '22', doneness: 'Hard', egg_size: 'M', temp:'Fridge', time:'9:40' },
{ key: '23', doneness: 'Hard', egg_size: 'L', temp:'Fridge', time:'10:40' },
{ key: '24', doneness: 'Hard', egg_size: 'XL', temp:'Fridge', time:'11:30' },
];
const [doneness, setDoneness] = useState();
const [eggsize, setEggSize] = useState();
const [temp, setTemp] = useState();
const [isReset, setisReset] = useState(false);
const [userCancelled, setUserCancelled] = useState(false);
//const [timerreset, setTimerreset] = useState(true);
function calcTime(doneness, eggsize, temp){
if(doneness == '' || eggsize == '' || temp == '')return;
console.log( "current params are: " + doneness + " " + eggsize + " " + temp)
//timer_presets
for(var i=0; i < timer_presets.length; i++){
//console.log(JSON.stringify(timer_presets[i].doneness, null, 2));
if(timer_presets[i].doneness == doneness && timer_presets[i].egg_size == eggsize && timer_presets[i].temp == temp ){
const timeparts = timer_presets[i].time.split(":");
var seconds = parseInt(timeparts[1]) + parseInt(timeparts[0]) * 60;
var time = new Date();
time.setSeconds(time.getSeconds() + seconds);
console.log('New time is: ' + timer_presets[i].time);
console.log('Seconds ' + seconds);
restart(time);
pause();
break;
}
}
}
return (
/*,borderWidth: 1, borderColor: 'black'*/
<NativeBaseProvider>
<View style={styles.container}>
<View style={styles.topHalfContainer}>
<View style={styles.timerDigitsContainer} >
<View style={styles.timerDigitsContainerV}>
<Text style={styles.timerNumbers}><Text style={styles.timerNumbers}>{String(hours).padStart(2, '0')}:{String(minutes).padStart(2, '0')}:{String(seconds).padStart(2, '0')}</Text></Text>
</View>
</View>
</View>
<View style={styles.bottomHalfContainer}>
<SafeAreaView style={{flex:1}}>
<ScrollView style={{flex:1}}>
<View><Text style={{ paddingVertical: 5, paddingHorizontal: 5, textAlign:'center'}}>Doneness</Text></View>
<View style={styles.container, {marginBottom: 10}}>
<RadioButton data={ [
{value: 'Soft', key: '1'},
{value: 'Medium', key: '2'},
{value: 'Hard', key: '3'}
] } onSelect={(value) => {
setDoneness(value);
calcTime(value, eggsize, temp);
}} />
</View>
<View><Text style={{ paddingVertical: 5, paddingHorizontal: 5, textAlign:'center'}}>Egg size</Text></View>
<View style={styles.container, {marginBottom: 10}}>
<RadioButton data={ [
{value: 'S', key: '1'},
{value: 'M', key: '2'},
{value: 'L', key: '3'},
{value: 'XL', key: '4'}
] } onSelect={(value) => {
setEggSize(value);
calcTime(doneness, value, temp);
}} />
</View>
<View><Text style={{ paddingVertical: 5, paddingHorizontal: 5, textAlign:'center'}}>Starting temp</Text></View>
<View style={styles.container, {marginBottom: 10}}>
<RadioButton data={ [
{value: 'Room Temp', key: '2'},
{value: 'Fridge', key: '3'}
] } onSelect={(value) => {
setTemp(value);
calcTime(doneness, eggsize, value);
}} />
</View>
<View style={{ /*borderColor:'black', borderWidth:1,*/ paddingHorizontal:30,paddingVertical:10, flex:1, alignItems:'center'}}>
{ !isRunning ?
<Pressable
disabled={(doneness == null || eggsize == null || temp == null) ? true : false}
style={[(doneness == null || eggsize == null || temp == null ? styles.disabled_style : null), styles.start_button]}
onPress={start}
><Text style={{color:'black',fontSize:30}}>Start</Text></Pressable>
:
<Pressable style={{borderRadius:30,paddingVertical:10,paddingHorizontal:70,backgroundColor:'#FCEBBF',color:'black', borderColor:'black', borderWidth:1 }}
onPress={() => {
var time = new Date();
restart(time);
setUserCancelled(true);
}}
><Text style={{color:'black',fontSize:30}}>Cancel</Text></Pressable>
}
</View>
</ScrollView>
</SafeAreaView>
</View>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
Alert.alert("Modal has been closed.");
setModalVisible(!modalVisible);
}}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>Time is up!</Text>
<TouchableHighlight activeOpacity={buttonActiveOpacity} underlayColor={buttonUnderlayColor}
style={[styles.button, styles.buttonClose]}
onPress={() => {
setModalVisible(!modalVisible);
sound.stopAsync();
}}
>
<Text style={styles.textStyle}>Dismiss</Text>
</TouchableHighlight>
</View>
</View>
</Modal>
</View>
</NativeBaseProvider>
);
}
if (!loaded) {
return null;
}
const time = new Date();
time.setSeconds(time.getSeconds());
return (
<SafeAreaView style={styles.container}>
<MyTimer expiryTimestamp={time} />
</SafeAreaView>
);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
