Related
i got this problem when i try to save all date in firebase realTime Database pressing submit.
ERROR TypeError: undefined is not an object (evaluating '_app.default.initializeApp')
import firebase from 'firebase';
import React, { useState } from 'react';
import { View, Text, Modal, TouchableOpacity, FlatList, StyleSheet, DatePickerIOS, Image } from 'react-native';
import { Picker } from '#react-native-picker/picker';
const App = () => {
const [chosenDate, setChosenDate] = useState(new Date());
const [selectedValue, setSelectedValue] = useState('Alege Specializarea');
const [selectedDoctor, setSelectedDoctor] = useState('');
const [modalVisible, setModalVisible] = useState(false);
const [showPicker, setShowPicker] = useState(false);
const [showButtons, setShowButtons] = useState(false);
const options = ['Alege Specializarea', 'Cardiologie', 'Dermatologie', 'Oftalmologie', 'Analize Medicale'];
const optionMapping = {
'Alege Specializarea': [],
'Cardiologie': ['Dr. Alex', 'Dr. Balut'],
'Dermatologie': ['Dr. Chloe', 'Dr. David'],
'Oftalmologie': ['Dr. Emily', 'Dr. Frank'],
'Analize Medicale': ['Dr. Grace', 'Dr. Henry'],
};
const firebaseConfig = {
apiKey: "AIzaSyBhyYCXEaUlXqr83GtcbAfV2fiFooGzm2k",
authDomain: "first-app-7901e.firebaseapp.com",
databaseURL: "https://first-app-7901e-default-rtdb.europe-west1.firebasedatabase.app",
projectId: "first-app-7901e",
storageBucket: "first-app-7901e.appspot.com",
messagingSenderId: "876718439254",
appId: "1:876718439254:web:afe7784b89f066210334f7",
};
firebase.initializeApp(firebaseConfig);
const writeAppointmentData = (appointment) => {
firebase
.database()
.ref('appointments/' + appointment.id)
.set(appointment);
};
// Read data from the database
const readAppointmentData = (appointmentId) => {
return firebase
.database()
.ref('appointments/' + appointmentId)
.once('value')
.then((snapshot) => {
return snapshot.val();
});
};
const handleSubmit = () => {
const appointment = {
date: chosenDate,
specialization: selectedValue,
doctor: selectedDoctor,
};
writeAppointmentData(appointment);
setModalVisible(true);
};
const handleRead = () => {
readAppointmentData(appointmentId).then((appointment) => {
setAppointment(appointment);
});
};
return (
<>
<View style={styles.container}>
<Image source={require('./book.png')} style={styles.image} />
</View>
<View style={styles.container}>
<DatePickerIOS
date={chosenDate}
onDateChange={setChosenDate}
minuteInterval={30}
/>
<TouchableOpacity
style={styles.selectionButton}
onPress={() => setShowPicker(!showPicker)}
>
<Text style={styles.selectionButtonText}>{selectedValue}</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.submitButton}
onPress={handleSubmit}
>
<Text style={styles.submitButtonText}>Submit</Text>
</TouchableOpacity>
{showPicker && (
<Picker
selectedValue={selectedValue}
style={styles.picker}
onValueChange={(itemValue) => {
setSelectedValue(itemValue);
setShowButtons(itemValue !== 'Alege Specializarea');
}}
>
{options.map((option) => (
<Picker.Item
label={option}
value={option}
key={option}
/>
))}
</Picker>
)}
{showButtons && optionMapping[selectedValue].length > 0 && (
<View style={styles.buttonContainer}>
{optionMapping[selectedValue].map((buttonName) => (
<TouchableOpacity
style={[
styles.button,
buttonName === selectedDoctor && {
backgroundColor: '#24b6d4',
},
]}
key={buttonName}
onPress={() => setSelectedDoctor(buttonName)}
>
<Text
style={[
styles.buttonText,
buttonName === selectedDoctor && { color: 'white' },
]}
>
{buttonName}
</Text>
</TouchableOpacity>
))}
</View>
)}
</View>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<Text style={styles.modalText}>
Your appointment has been scheduled for{' '}
{chosenDate.toString()} with {selectedDoctor}
</Text>
<TouchableOpacity
style={styles.modalButton}
onPress={() => setModalVisible(false)}
>
<Text style={styles.modalButtonText}>Close</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</>
);
};
const styles = StyleSheet.create({
container: {
top: -160,
flex: 1,
width: 350,
justifyContent: 'center',
},
image: {
alignSelf: 'center',
},
selectionButton: {
backgroundColor: 'lightgray',
padding: 10,
borderRadius: 10,
left: 20,
},
selectionButtonText: {
fontSize: 18,
},
picker: {
width: '100%',
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'center',
},
button: {
backgroundColor: '#fff',
borderWidth: 1,
borderColor: '#24b6d4',
borderRadius: 10,
padding: 10,
margin: 10,
width: 120,
},
buttonText: {
color: '#24b6d4',
fontSize: 18,
textAlign: 'center',
},
submitButton: {
backgroundColor: '#24b6d4',
borderRadius: 10,
padding: 10,
margin: 10,
},
submitButtonText: {
color: 'white',
fontSize: 18,
textAlign: 'center',
},
centeredView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
marginTop: 22,
},
modalView: {
margin: 20,
backgroundColor: 'white',
borderRadius: 20,
padding: 35,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
modalText: {
marginBottom: 15,
textAlign: 'center',
},
modalButton: {
backgroundColor: '#24b6d4',
borderRadius: 10,
padding: 10,
margin: 10,
},
modalButtonText: {
color: 'white',
fontSize: 18,
textAlign: 'center',
},
});
export default App;
I use ExpoGO to "export" the project.
I tried many changes at firebase like: import firebase from 'firebase'; and all that changes for import firebase,none of that works but i tried with Firebase JS SDK and still dosent work.
In our code we want the individual button to update style on press and to be able to basically have it update state to where we know it is pressed and can send that it was taken to our database when the submit button is pressed. We have the submit button working but we can't seem to update the seat buttons when we press them to change their color. Instead, we have to wait and reload the page before it changes anything. Here is the code below.
export const OrderScreen = ({ navigation }) => {
const [counter, setCounter] = useState(0);
LogBox.ignoreLogs(['Setting a timer']);
const [order, setOrder] = useState('Unknown');
const COL = 5;
const [data, setData] = useState([]);
const [seats, setSeats] = useState([]);
const updateSeat = async (taken,rowNum,seat) => {
const DocRef = doc(db, "Theaters/Seating/Theater1", rowNum);
await updateDoc(DocRef, {
[seat] : taken
});
};
var ListofOrders = [];
function recordOrder(name,qty){
console.log(name, qty);
ListofOrders = ListofOrders.filter(function( element ) {
return element !== undefined;
});
if(ListofOrders.length != 0){
for (let i = 0; i < ListofOrders.length; i++ ){
//console.log(ListofOrders[i][0]);
if(ListofOrders[i][0] == name){
delete ListofOrders[i];
}
}
}
var array = [name,qty];
ListofOrders.push(array);
//console.log(ListofOrders);
};
const SubmitOrder = async() =>{
for (let i = 0; i < ListofOrders.length; i++ ){
const q = query(collection(db, 'Inventory'), where("name" , "==" , ListofOrders[i][0]));
//console.log(ListofOrders[i][0]);
const querySnapshot = getDocs(q);
querySnapshot.forEach((doc) => {
console.log(doc.id);
docid = doc.id;
});
const dbRef = doc(db, 'Inventory', docid);
updateDoc(dbRef, {
qty: ListofOrders[i][1]
});
}
console.log("successful");
};
function seatTaken(position){
switch(position){
case true: return(styles.seatButton); break;
case false: return(styles.seatButtonTaken); break;
}
};
//function handleClick (){
// setState('buttontaken')
// }
useEffect(() => {
const getInventory = async () => {
const inventorySnapshot = await getDocs(collection(db, "Inventory"));
const inventoryList = inventorySnapshot.docs.map((doc) => doc.data());
setData(inventoryList);
// console.log(inventoryList);
};
getInventory();
const getSeating = async () => {
const seatSnapshot = await getDocs(collection(db, "Theaters/Seating/Theater1"));
const seatList = seatSnapshot.docs.map((doc) => doc.data());
setSeats(seatList);
//console.log(seatList);
};
getSeating();
}, [])
return (
<View style={styles.container}>
<ScrollView>
<Text style={styles.screenTitle}>New Order</Text>
{/* Theater Selection */}
<Text style ={styles.text}> Ticket Order</Text>
<Picker
selectedValue={order}
onValueChange={(value, index) => setOrder(value)}
mode="dropdown" // Android only
style={styles.picker}
>
<Picker.Item label="Please select your Order" value="Unknown" />
<Picker.Item label="Theater 1 5PM" value="Theater 1" />
<Picker.Item label="Theater 2 5PM" value="Theater 2" />
</Picker>
{/* Seat Animation */}
{seats.map((seats,index1,index2,index3) =>(
<React.Fragment>
<View style = {styles.containerseats}>
<Text style = {styles.itemText}> Row {index1 + 1} </Text>
<Button key = {seats} style = {seatTaken(seats.A)} onPress = {() => updateSeat(false, 'Row' + (index1 + 1),'A')}/>
<Button key = {index1} style = {seatTaken(seats.B)} onPress = {() => updateSeat(false, 'Row' + (index1 + 1),'B')}/>
<Button key = {index2} style = {seatTaken(seats.C)} onPress = {() => updateSeat(false, 'Row' + (index1 + 1),'C')}/>
<Button key = {index3} style = {seatTaken(seats.D)} onPress = {() => updateSeat(false, 'Row' + (index1 + 1),'D')} />
</View>
</React.Fragment>
))}
{/* Food order */}
{data.map((data,qty) =>(
<React.Fragment>
<View style = {styles.parent}>
<View style = {styles.block}>
<Text key = {data} style = {styles.itemText}> {data.name}</Text>
</View>
<View style = {styles.block} >
<Counter start = {parseInt(0)} max = {parseInt(data.qty)} onChange={(len, type) => {
console.log(len, type);
qty = len;
recordOrder(data.name,qty);
}} />
</View>
</View>
</React.Fragment>
))}
{/* Buttons */}
<Button style={styles.buttonsubmit} onPress = {() => SubmitOrder()}>
<Text style={styles.buttonText}>Submit Order</Text>
</Button>
<Button style={styles.borderlessButtonContainer} borderless
title={'Cancel Order'}
onPress = {() => navigation.navigate('CustomerHomeScreen')} />
</ScrollView>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'black',
paddingHorizontal: 12,
alignItems: 'center'
},
screenTitle: {
fontSize: 18,
fontWeight: '700',
color: Colors.orange,
paddingTop: 10,
textAlign: 'center',
},
text: {
fontSize: 18,
fontWeight: '700',
color: Colors.orange,
paddingTop: 10,
textAlign: 'center',
},
button: {
width: '10%',
height: 18,
marginTop: 8,
alignItems: 'center',
backgroundColor: Colors.orange,
padding: 10,
borderRadius: 8,
marginRight:8
},
buttonsubmit: {
width: '50%',
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
marginTop: 8,
backgroundColor: Colors.orange,
padding: 10,
borderRadius: 8,
},
buttontaken: {
width: '10%',
height: 18,
marginTop: 8,
backgroundColor: Colors.black,
borderColor: Colors.white,
padding: 10,
borderWidth:2,
borderRadius:8,
marginRight:8,
alignItems: 'center',
justifyContent: 'center',
},
buttonText: {
fontSize: 20,
color: Colors.white,
fontWeight: '700',
},
borderlessButtonContainer: {
marginTop: 16,
alignItems: 'center',
},
picker: {
marginVertical: 30,
width: 300,
padding: 10,
borderWidth: 5,
color: Colors.black,
backgroundColor: 'white',
},
containerseats: {
flexDirection: 'row',
flex: 1,
alignContent: 'space-around',
padding: 5
},
seatButton: {
width: '10%',
height: 18,
marginTop: 8,
backgroundColor: Colors.orange,
padding: 10,
borderRadius: 8,
marginRight:8
},
seatButtonTaken: {
width: '10%',
height: 18,
marginTop: 8,
backgroundColor: Colors.black,
borderColor: Colors.white,
padding: 9,
borderWidth:2,
borderRadius:8,
marginRight:8,
alignItems: 'center',
justifyContent: 'flex-end',
},
itemText: {
fontSize: 20,
fontWeight: '500',
color: '#ff9361',
},
parent: {
flexDirection: "row",
},
block: {
flex: 3,
margin: 6,
},
});
It is pulling from a firebase database and looks like the image below. I would like the button I press to immediately update the style of that button to seatbuttontaken style instead of seatbutton. Please let me know if there's any other helpful information I can provide.
So I have this code here. I don't know if it's cause of how I structured it, but the state changes using the 'set' function doesn't change the state till after I change the entry again. So for example, I'll put in text then I push "post" which should update the state, when console.warn prints it doesn't print anything. Then I change the text again and push post and console.warn will output what was there before my most recent change.
import React, {useState, createRef} from 'react';
import LinearGradient from 'react-native-linear-gradient';
import {
StyleSheet,
TextInput,
View,
Text,
ScrollView,
Keyboard,
Button,
TouchableOpacity,
KeyboardAvoidingView,
} from 'react-native';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import Loader from '../components/Loader';
const GoalRegistrationScreen = ({navigation}) => {
const [isDatePickerVisible, setDatePickerVisibility] = useState(false);
const [goalText, setGoal] = useState('');
const [durationText, setDuration] = useState('');
const [descriptionText, setDescription] = useState('');
const [loading, setLoading] = useState(false);
const [errortext, setErrortext] = useState('');
const durationInputRef = createRef();
const descriptionInputRef = createRef();
function showDatePicker() {
setDatePickerVisibility(true);
}
function hideDatePicker() {
setDatePickerVisibility(false);
}
function handleConfirm(date) {
hideDatePicker();
console.warn(date);
}
function onButtonClick() {
// console.warn(goalText)
console.warn(descriptionText);
}
React.useLayoutEffect(() => {
navigation.setOptions({
title: 'Create Goal',
headerTitleAlign: 'center',
headerRight: () => (
<TouchableOpacity
style={styles.addButtonStyle}
activeOpacity={0.5}
onPress={onButtonClick}>
<LinearGradient
colors={['#FBE049', '#4964FB']}
style={styles.linearGradient}
start={{x: 0, y: 0}}
end={{x: 1, y: 1}}>
<Text style={styles.buttonTextStyle}>Post</Text>
</LinearGradient>
</TouchableOpacity>
),
});
}, [navigation]);
return (
<View style={styles.mainBody}>
<Loader loading={loading} />
<ScrollView keyboardShouldPersistTaps="handled">
<View>
<KeyboardAvoidingView enabled>
<View style={styles.SectionStyle}>
<TextInput
style={styles.inputStyle}
onChangeText={goal => setGoal(goal)}
placeholder="What do I want to accomplish?"
placeholderTextColor="#8b9cb5"
autoCapitalize="none"
returnKeyType="next"
onSubmitEditing={() =>
durationInputRef.current && durationInputRef.current.focus()
}
underlineColorAndroid="#f000"
blurOnSubmit={false}
/>
</View>
<View style={styles.SectionStyle}>
<Button title="Show Date Picker" onPress={showDatePicker} />
<DateTimePickerModal
isVisible={isDatePickerVisible}
mode="date"
onConfirm={handleConfirm}
onCancel={hideDatePicker}
minimumDate={new Date()}
/>
{/* <TextInput
style={styles.inputStyle}
onChangeText={duration => setDuration(duration)}
placeholder="Duration of Goal"
placeholderTextColor="#8b9cb5"
keyboardType="default"
ref={durationInputRef}
onSubmitEditing={() =>
descriptionInputRef.current &&
descriptionInputRef.current.focus()
}
blurOnSubmit={false}
underlineColorAndroid="#f000"
returnKeyType="next"
/> */}
</View>
<View style={styles.SectionStyle}>
<TextInput
style={styles.accomplishmentTextStyle}
onChangeText={description => setDescription(description)}
placeholder="How can I accomplish this goal?"
placeholderTextColor="#8b9cb5"
keyboardType="default"
ref={descriptionInputRef}
onSubmitEditing={Keyboard.dismiss}
blurOnSubmit={false}
underlineColorAndroid="#f000"
returnKeyType="next"
/>
</View>
{errortext != '' ? (
<Text style={styles.errorTextStyle}>{errortext}</Text>
) : null}
</KeyboardAvoidingView>
</View>
</ScrollView>
</View>
);
};
export default GoalRegistrationScreen;
const styles = StyleSheet.create({
mainBody: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#FFFFFF',
alignContent: 'center',
},
SectionStyle: {
flexDirection: 'row',
marginLeft: 35,
marginRight: 35,
margin: 10,
},
buttonTextStyle: {
color: '#000000',
paddingVertical: 10,
fontSize: 16,
paddingLeft: 15,
paddingRight: 15,
borderRadius: 32,
borderColor: '#000000',
},
inputStyle: {
flex: 1,
color: 'black',
paddingLeft: 15,
paddingRight: 15,
borderWidth: 1,
borderRadius: 30,
borderColor: '#000000',
},
accomplishmentTextStyle: {
flex: 1,
color: 'black',
paddingLeft: 15,
paddingRight: 15,
borderWidth: 1,
borderRadius: 30,
borderColor: '#000000',
height: 150,
textAlignVertical: 'top',
},
addButtonStyle: {
paddingRight: 20,
},
linearGradient: {
borderRadius: 32,
},
errorTextStyle: {
color: 'red',
textAlign: 'center',
fontSize: 14,
},
});
Here's an example I had 'testdsdd' in the description and updated to 'test', the onChangeText function should automatically have changed it to 'test', but it didn't. This happens for all states from goalText, descriptionText to setting date.
Try to change the TextInput onChangeText prop to just onChange like this:
onChangeText={ handleInputChange }
and then handle the new input in the handleInputChange:
const handleInputChange = useCallback((ev) => {
const input = ev.nativeEvent.text;
// you can also do error checking here.
setDescription(input);
}, [formatMessage]);
I always suggest using a pattern like this because it allows you to check for errors or call other methods (like auto-search).
In fact, I suggest using the handleInputChange to check for errors and only set the new state for the text-input on an onEndEditing.
Below is the code component for the customer picker
import React, { useEffect, useState } from "react";
import { connect } from 'react-redux';
import {
TouchableOpacity,
FlatList,
SafeAreaView,
StatusBar,
StyleSheet,
Text,
View,
Button,
Alert,
} from "react-native";
import { screenHeight, screenWidth } from "../constants";
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
title: "Client Not Found"
},
{
id: "58694a0f-3da1-471f-bd96-145571e29d72",
title: "Client refused"
},
];
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} style={[styles.item, style]}>
<Text style={styles.title}>{item.title}</Text>
</TouchableOpacity>
);
const StatusOptions = (props) => {
const [selectedId, setSelectedId] = useState(null);
const renderSeparator = () => (
<View
style={{
backgroundColor: "grey",
height: 0.8
}}
/>
);
const ListHeader = () => {
//View to set in Header
return (
<View style={{ height: 20 }}></View>
);
};
const renderItem = ({ item }) => {
const backgroundColor = item.id === selectedId ? "#6cd9ff" : "white";
return (
<Item
item={item}
onPress={() => {
setSelectedId(item.id);
console.log("SELECTED ID _ STATUSOPTIONS component : ", selectedId);
const val = DATA.filter(status => status.id == selectedId).map(filteredStatus => filteredStatus.title);
console.log("VALLLLLLLLLLLLLLLLLLLLLLLUUUUUUEEEEEEEEEEEEEEEEEEEE:::: ", val);
props.navigation.navigate('AnotherScreen');
}}
style={{ backgroundColor }}
/>
);
};
return (
<View style={{ bottom: 0, flex: 1, position: 'absolute', width: screenWidth, }}>
<View style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
ItemSeparatorComponent={renderSeparator}
ListHeaderComponent={ListHeader}
style={{
backgroundColor: "white",
width: "100%",
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
zIndex: 1,
}}
/>
</View>
<View style={{ backgroundColor: "grey", height: 0.4 }} />
<View style={styles.closeButtonContainer}>
<TouchableOpacity style={styles.closeButton}
onPress={() => {
props.setStatusOptionsVisible(false)
}}>
<Text style={styles.title}>Close</Text>
</TouchableOpacity>
</View>
</View>
);
};
function mapStateToProps(state) {
return {
StatusOptionsVisible: state.volunteerItems.statusOptionsVisible,
currentTaskItemId: state.taskItems.taskItemId,
};
}
function mapDispatchToProps(dispatch) {
return {
setStatusOptionsVisible: (visible) => dispatch({ type: 'SET_STATUS_VISIBLE', statusVisibility: visible }),
};
}
export default connect(mapStateToProps, mapDispatchToProps)(StatusOptions);
const styles = StyleSheet.create({
closeButton: {
backgroundColor: 'lightgrey',
borderRadius: 10,
height: 50,
justifyContent: 'center',
width: '90%',
},
closeButtonContainer: {
alignItems: 'center',
height: 90,
justifyContent: 'center',
backgroundColor: 'white',
},
textStyle: {
textAlign: "center",
},
container: {
borderRadius: 30,
flex: 4,
width: screenWidth,
},
item: {
padding: 20
},
title: {
fontSize: 20,
fontWeight: 'bold',
color: "black",
textAlign: "center"
}
});
the console Log : ("SELECTED ID _ STATUSOPTIONS component : ", selectedId)
in render Item function returns null for first picker item selection and the returns the previous value for the next picker item selection , can anyone please help with fixing it ?
Try to use this
useEffect(() => {
console.log("SELECTED ID _ STATUSOPTIONS component : ", selectedId);
if(selectedId != null) {
const val = DATA.filter(status => status.id == selectedId).map(filteredStatus => filteredStatus.title);
console.log("VALLUUEEEEEEEEEEEEEEEEEEEE:::: ", val);
}
}, [selectedId])
I'm trying to make a toy stopwatch app in order to learn react-native.
I made a lap system, but it is getting way too slow when there are >15 laps. I think the poor performance point is the laps: this.state.laps.concat([d - this.state.lapTimerStart]) part, because of .concat is making a new object every time the Lap button is pressed.
I've heard that .push is way faster than .concat.
So I tried to use .push, but because .push was mutating the array, and FlatList was a PureComponent so it re-rendered only when the props have changed.
I found a way, but it was just the same as doing .concat because basically, it was
let lapArr = this.state.laps;
Array.prototype.push.apply(lapArr, [d - this.state.lapTimerStart]);
this.setState({
laps: lapArr,
})
The full code is
import React, {Component} from 'react';
import {
View,
Text,
StyleSheet,
TouchableHighlight,
FlatList,
} from 'react-native';
import {useTheme} from 'react-native-paper';
import TimeFormatter from 'minutes-seconds-milliseconds';
class Stopwatch extends Component {
constructor(props) {
super(props);
this.state = {
laps: [],
isRunning: false,
mainTimer: null,
lapTimer: null,
mainTimerStart: null,
lapTimerStart: null,
};
}
handleLapReset() {
let {isRunning, mainTimerStart, lapTimer} = this.state;
if (mainTimerStart) {
if (isRunning) {
const d = new Date();
this.setState({
lapTimerStart: d,
lapTimer: d - this.state.lapTimerStart + lapTimer,
laps: this.state.laps.concat([d - this.state.lapTimerStart]),
});
return;
}
this.state.laps = [];
this.setState({
mainTimerStart: null,
lapTimerStart: null,
mainTimer: 0,
lapTimer: 0,
});
}
}
handleStartStop() {
let {isRunning, mainTimer, lapTimer} = this.state;
if (isRunning) {
clearInterval(this.interval);
this.setState({
isRunning: false,
});
return;
}
const d = new Date();
this.setState({
mainTimerStart: d,
lapTimerStart: d,
isRunning: true,
});
this.interval = setInterval(() => {
const t = new Date();
this.setState({
mainTimer: t - this.state.mainTimerStart + mainTimer,
lapTimer: t - this.state.lapTimerStart + lapTimer,
});
}, 10);
}
_renderTimers() {
const {theme} = this.props;
return (
<View
style={[
styles.timerWrapper,
{backgroundColor: theme.colors.background},
]}>
<View style={styles.timerWrapperInner}>
<Text style={[styles.lapTimer, {color: theme.colors.text}]}>
{TimeFormatter(this.state.lapTimer)}
</Text>
<Text style={[styles.mainTimer, {color: theme.colors.text}]}>
{TimeFormatter(this.state.mainTimer)}
</Text>
</View>
</View>
);
}
_renderButtons() {
const {theme} = this.props;
return (
<View style={styles.buttonWrapper}>
<TouchableHighlight
underlayColor={theme.colors.disabled}
onPress={this.handleLapReset.bind(this)}
style={[styles.button, {backgroundColor: theme.colors.background}]}>
<Text style={[styles.lapResetBtn, {color: theme.colors.text}]}>
{this.state.mainTimerStart && !this.state.isRunning
? 'Reset'
: 'Lap'}
</Text>
</TouchableHighlight>
<TouchableHighlight
underlayColor={theme.colors.disabled}
onPress={this.handleStartStop.bind(this)}
style={[styles.button, {backgroundColor: theme.colors.background}]}>
<Text
style={[styles.startBtn, this.state.isRunning && styles.stopBtn]}>
{this.state.isRunning ? 'Stop' : 'Start'}
</Text>
</TouchableHighlight>
</View>
);
}
_renderLaps() {
return (
<View style={styles.lapsWrapper}>
<FlatList
data={this.state.laps}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
/>
</View>
);
}
keyExtractor(item, index) {
return index.toString();
}
renderItem({item, index}) {
return (
<View style={styles.lapRow}>
<View style={styles.lapStyle}>
<View style={styles.lapBoxStyle} />
<Text style={styles.lapNumber}>{index + 1}</Text>
</View>
<View style={styles.lapStyle}>
<Text style={styles.lapTime}>{TimeFormatter(item)}</Text>
</View>
</View>
);
}
render() {
return (
<View style={styles.container}>
<View style={styles.top}>{this._renderTimers()}</View>
<View style={styles.middle}>{this._renderButtons()}</View>
<View style={styles.bottom}>{this._renderLaps()}</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {flex: 1},
timerWrapper: {
justifyContent: 'center',
flex: 1,
},
top: {
flex: 1,
},
middle: {
flex: 1,
backgroundColor: '#F0EFF5',
},
bottom: {
flex: 2,
},
mainTimer: {
fontSize: 50,
fontFamily: 'CircularStd-Medium',
alignSelf: 'center',
},
lapTimer: {
fontSize: 18,
fontFamily: 'CircularStd-Medium',
alignSelf: 'flex-end',
},
timerWrapperInner: {
alignSelf: 'center',
},
buttonWrapper: {
flexDirection: 'row',
justifyContent: 'space-around',
paddingTop: 15,
paddingBottom: 30,
},
button: {
height: 80,
width: 80,
borderRadius: 40,
backgroundColor: '#FFF',
justifyContent: 'center',
alignItems: 'center',
},
lapRow: {
flexDirection: 'row',
justifyContent: 'space-between',
height: 40,
paddingTop: 10,
},
lapNumber: {
flexDirection: 'row',
fontSize: 16,
fontFamily: 'CircularStd-Book',
color: '#777',
flex: 1,
},
lapTime: {
flexDirection: 'row',
color: '#000',
fontSize: 20,
fontFamily: 'CircularStd-Book',
flex: 1,
},
startBtn: {
color: '#0C0',
fontFamily: 'CircularStd-Book',
},
stopBtn: {
color: '#C00',
fontFamily: 'CircularStd-Book',
},
lapsWrapper: {
backgroundColor: '#ddd',
},
lapResetBtn: {
fontFamily: 'CircularStd-Book',
},
lapStyle: {
width: '40%',
flexDirection: 'row',
},
lapBoxStyle: {
flexDirection: 'row',
flex: 1,
},
});
export default function StopwatchScreen(props) {
const theme = useTheme();
return <Stopwatch {...props} theme={theme} />;
}
I tried not to use arrow functions, many news, but it didn't help that much.
FlatList is a pure component and it is mandatory to give new ref of data prop to render list . You should use concat but it created new object.
i think the main issue is renderItem.
create a separate PureComponent to avoid re-rendeing of items
class Item extends PureComponent {
const {item,index} = this.props;
return (
<View style={styles.lapRow}>
<View style={styles.lapStyle}>
<View style={styles.lapBoxStyle} />
<Text style={styles.lapNumber}>{index + 1}</Text>
</View>
<View style={styles.lapStyle}>
<Text style={styles.lapTime}>{TimeFormatter(item)}</Text>
</View>
</View>
);
}
and use in render item
renderItem({item, index}) {
return (
<Item item={item} index={index} />
);
}