'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