My app wasn't able to rerender on installation startup 'singleton' that I have created ONLY when I generate the apk file through eam build.
It is working when I use expo-go
I have click on one of the other button (this case, my own create exercise button) for it to force rerender again. this create button sets a useState to render a 'Modal'
I am really tired of working on this. Hope there is some suggestions for this bug.
App.tsx
import {
Alert, LogBox
} from 'react-native'
import { ExercisesScreen } from './screens/ExercisesScreen'
import { SettingsScreen } from './screens/SettingsScreen'
import { PlanScreen } from './screens/ScheduleScreen'
import React, { useState, useEffect } from 'react'
import { NavigationContainer } from '@react-navigation/native'
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs'
import {
init, resetTables, createScheduledItem, deleteScheduledItem, updateScheduledItem,
createExerciseMajorMuscleRelationship, createExercise,
deleteExerciseMajorMuscleRelationship, deleteExercise, updateExercise,
retrieveExerciseMajorMuscleRelationships, retrieveMajorMuscles,
retrieveScheduledItems, retrieveExercises, deleteFromExerciseAndScheduledItem
} from './dbhandler'
import {
ButtonSetProps, ContextProps, DialogState, Exercise, ExerciseState,
MajorMuscle, PushPullEnum, ScheduledItemState
} from './types'
import { ScheduledItem } from './types'
import Toast from 'react-native-simple-toast'
import Colors from './constants/Colors'
import { DateData } from 'react-native-calendars'
import { Ionicons, MaterialCommunityIcons, } from '@expo/vector-icons'
import _default from 'babel-plugin-transform-typescript-metadata'
import { ScheduleDialog } from './screens/ScheduleDialog'
import { ExerciseDialog } from './screens/ExerciseDialog'
import { styles } from './constants/styles'
import { SelectDateDialog } from './screens/SelectDateDialog'
import { StorageAccessFramework } from 'expo-file-system'
import {
ExerciseInformationText, EditExerciseText,
CreateExerciseText, ScheduledItemInformation,
EditScheduledItemText, DuplicateScheduledItemText, CreateScheduledItemText
} from './constants/strings'
import {
initialExerciseState, initialScheduledItemState, initialMajorMuscles,
initialEmm, initialDialogState, initialScheduledItem, ExerciseScreenContext,
ScheduledItemContext, SettingsScreenContext
} from './constants/initialValues'
import * as DocumentPicker from 'expo-document-picker'
LogBox.ignoreLogs(['Require cycle:'])
const Tab = createBottomTabNavigator()
export default function App() {
const [exerciseState, setExerciseState] = useState<ExerciseState>(initialExerciseState)
const [scheduledItemState, setScheduledItemState] =
useState<ScheduledItemState>(initialScheduledItemState)
const [dialogState, SetDialogState] = useState<DialogState>(initialDialogState)
const [emm, setEmm] = useState(initialEmm)
const [dropDownMajorMuscleNameSelected, setDropDownMajorMuscleValues] = useState([""])
const [dropDownExNameSelected, setDropDownExNameSelected] = useState("")
const [dropDownPushPullSelected, setDropDownPushPullSelected] = useState(PushPullEnum.Push)
function handlePlanHeader(date: DateData) {
const s: string = ("Plan " + date.day + "-" + date.month + "-" + date.year)
SetDialogState({ ...dialogState, planHeader: s })
}
useEffect(() => {
let tempExercises: Exercise[]
if (exerciseState.exercises[0] != undefined)
if (exerciseState.exercises[0].name == ""
|| exerciseState.exercises.length <= 0)
retrieveExercises((_, r) => {
tempExercises = r.rows._array
tempExercises.forEach(ex => ex.major_muscles = initialMajorMuscles)
if (scheduledItemState.scheduledItems[0] != undefined)
if (scheduledItemState.scheduledItems[0].exercise
== initialExerciseState.aExercise)
retrieveScheduledItems(
(_, results) => {
const tempScheduledItems: ScheduledItem[] = results.rows._array
const a = results.rows._array.slice()
tempScheduledItems.forEach((ms, index) => {
ms.date = JSON.parse(ms.date.toString())
const t = tempExercises.find(ex => ex.name == a[index].exercise)
tempScheduledItems[index].exercise = t!
})
setScheduledItemState({
...scheduledItemState,
scheduledItems: tempScheduledItems,
filteredScheduledItems: tempScheduledItems
})
})
setExerciseState({
...exerciseState, exercises: tempExercises,
filteredExercises: tempExercises
})
})
if (exerciseState.majorMuscles[0] == initialMajorMuscles[0]) {
retrieveMajorMuscles(
(_, results) => setExerciseState({
...exerciseState,
majorMuscles: results.rows._array
}))
}
if (emm[0] == initialEmm[0])
retrieveExerciseMajorMuscleRelationships(
(_, results) => setEmm(results.rows._array))
if (exerciseState.majorMuscles.length > 1
&& exerciseState.exercises.length > 1
&& emm.length > 1) {
emm.forEach(x => {
const ex: Exercise =
exerciseState.exercises.find(e => e.name == x.exercise_name)!
const mm2: MajorMuscle = exerciseState
.majorMuscles
.find(mm => mm.name == x.major_muscle_name)!
if (ex == undefined || mm2 == undefined) return
if (ex.major_muscles == initialMajorMuscles)
ex.major_muscles = [mm2!]
else if (!ex.major_muscles.find(x => x.name == mm2.name))
ex.major_muscles.push(mm2!)
})
}
}, [scheduledItemState, exerciseState, emm])
init()
let textInputStyle, numberInputStyle
if (dialogState.isEditable) {
textInputStyle = styles.textInputEditable
numberInputStyle = styles.numberInputEditable
} else {
textInputStyle = styles.textInputViewOnly
numberInputStyle = styles.numberInputViewOnly
}
const handleResetDB = () => {
resetTables()
setExerciseState(initialExerciseState)
setScheduledItemState(initialScheduledItemState)
SetDialogState(initialDialogState)
setEmm(initialEmm)
}
//Android only export and import
async function handleExport() {
const exportData = {
exercises: exerciseState.exercises,
scheduledItems: scheduledItemState.scheduledItems
}
const permissions = await StorageAccessFramework.requestDirectoryPermissionsAsync()
if (!permissions.granted) return
let uri = await StorageAccessFramework.createFileAsync(
permissions.directoryUri, "GymTracker backup", "application/json"
)
await StorageAccessFramework.writeAsStringAsync(uri, JSON.stringify(exportData))
Alert.alert("", `The backup data is now saved in the approved folder as `
+ `GymTracker backup.json`
+ `\nNote: if there is multiple backups, it will be numbered.`,
[{
text: "Cancel",
onPress: () => { },
style: "cancel"
}],
{ cancelable: true }
)
}
async function handleImport() {
Toast.show("Please grant folder permissions.")
const permissions =
await StorageAccessFramework
.requestDirectoryPermissionsAsync()
if (!permissions.granted) return
Toast.show("Please choose the correct json file")
let documentResult: DocumentPicker.DocumentResult =
await DocumentPicker.getDocumentAsync({ type: 'application/json' })
if (documentResult.type == 'cancel') return
const data = JSON.parse(
await StorageAccessFramework
.readAsStringAsync(documentResult.uri))
console.log(data)
if (!('exercises' in data) || !('scheduledItems' in data)) {
Toast.show("The data does not have the correct format")
return
}
if (!Array.isArray(data.exercises)
|| !Array.isArray(data.scheduledItems)) {
Toast.show("The data does not have the correct format")
return
}
deleteFromExerciseAndScheduledItem()
setExerciseState({
...exerciseState,
exercises: data.exercises,
filteredExercises: data.exercises
})
setScheduledItemState({
...scheduledItemState,
scheduledItems: data.scheduledItems,
filteredScheduledItems: data.scheduledItems
})
data.exercises.forEach((ex: Exercise) => createExercise(ex))
console.log(scheduledItemState.scheduledItems)
data
.scheduledItems
.forEach((si: ScheduledItem) => createScheduledItem(si))
}
function cancelDialog() {
SetDialogState({
...dialogState,
isExDialogVisible: false,
isCalendarDialogVisible: false,
isPlanDialogVisible: false
})
}
// Exercises Functions:
//renders
const renderExerciseDialogForViewing = (exercise: Exercise) => {
textInputStyle = styles.textInputViewOnly
setExerciseState({
...exerciseState,
aExercise: exercise,
oldExerciseName: exercise.name
})
const names: string[] = []
exercise.major_muscles.forEach(mm => names.push(mm.name))
setDropDownMajorMuscleValues(names)
setDropDownPushPullSelected(exercise.push_or_pull)
SetDialogState({
...dialogState,
isExDialogVisible: true, openPushPullDropDown: false,
dialogText: ExerciseInformationText,
isEditable: false, isDropDownOpen: false,
})
}
const renderExerciseDialogForEdit = () => {
textInputStyle = styles.textInputEditable
SetDialogState({
...dialogState,
isEditable: true,
dialogText: EditExerciseText,
isDropDownOpen: false,
openPushPullDropDown: false
})
}
const renderExerciseDialogForCreate = () => {
setExerciseState({
...exerciseState, aExercise:
initialExerciseState.aExercise
})
setDropDownMajorMuscleValues([])
textInputStyle = styles.textInputEditable
SetDialogState({
...dialogState,
isExDialogVisible: true, openPushPullDropDown: false,
dialogText: CreateExerciseText, isEditable: true, isDropDownOpen: false
})
setDropDownPushPullSelected(PushPullEnum.Push)
}
//db
const commonExercisesCRUD = (es: Exercise[]) => {
setExerciseState({
...exerciseState, exercises: [...es],
filteredExercises: [...es],
filteredExerciseKeyword: ""
})
cancelDialog()
}
const deleteExerciseConfirmation = (exercise: Exercise) => {
Alert.alert(
"Confirmation",
"Are you sure you want to delete this exercise?",
[{
text: "Yes",
onPress: () => deleteExerciseWithStateUpdate(exercise)
},
{
text: "No",
onPress: () => renderExerciseDialogForViewing(exercise)
}],//warning, recursive-
{ cancelable: true }
)
}
const deleteExerciseWithStateUpdate = (exercise: Exercise) => {
const selected: MajorMuscle[] = exerciseState.majorMuscles.filter(
x => dropDownMajorMuscleNameSelected.includes(x.name))
selected.forEach(
x => deleteExerciseMajorMuscleRelationship(exercise.name, x.name))
deleteExercise(exercise.name, () => {
const deletedName = exercise.name
const es: Exercise[] = exerciseState.exercises.slice()
es.forEach((currentExercise, i) => {
if (currentExercise.name == deletedName) {
es.splice(i, 1)
return
}
})
//correct way of removing element from a array for me. Not using delete keyword which leaves a undefined space
Toast.show("The exercise " + deletedName + " has is deleted.")
commonExercisesCRUD(es)
})
}
const updateExerciseWithStateUpdate = () => {
const aExercise = exerciseState.aExercise
if (aExercise.name.trim() == "") {
Toast.show("name cannot be empty")
return
}
const oldExerciseName = exerciseState.oldExerciseName
const pushPullDropDownValue = dropDownPushPullSelected
const selected: MajorMuscle[] = exerciseState.majorMuscles.filter(
x => dropDownMajorMuscleNameSelected.includes(x.name))
const toBeCreated: MajorMuscle[] = selected.filter(
x => !aExercise.major_muscles.find(t => t.name == x.name))
const toBeDeleted: MajorMuscle[] = aExercise.major_muscles.filter(
x => !selected.find(t => t.name == x.name))
toBeCreated.forEach(
x => createExerciseMajorMuscleRelationship(aExercise.name, x.name))
toBeDeleted.forEach(
x => deleteExerciseMajorMuscleRelationship(aExercise.name, x.name))
aExercise.push_or_pull = pushPullDropDownValue
updateExercise(aExercise, oldExerciseName,
() => {
const exerciseToBeUpdated: Exercise = {
name: aExercise.name, description: aExercise.description,
imagesJson: aExercise.imagesJson,
major_muscles: selected, push_or_pull: dropDownPushPullSelected
}
const es: Exercise[] = exerciseState.exercises.slice()
es.forEach((currentExercise, i) => {
if (currentExercise.name == oldExerciseName) {
es.splice(i, 1, exerciseToBeUpdated)
return
}
})
commonExercisesCRUD(es)
Toast.show("The exercise is updated.")
})
}
function createExerciseWithStateUpdate() {
const aExercise = exerciseState.aExercise
if (aExercise.name == "") {
Toast.show("name cannot be empty")
return
}
const selected: MajorMuscle[] = exerciseState.majorMuscles.filter(
x => dropDownMajorMuscleNameSelected.includes(x.name))
selected.forEach(
x => createExerciseMajorMuscleRelationship(aExercise.name, x.name))
aExercise.push_or_pull = dropDownPushPullSelected
console.log(aExercise.push_or_pull)
createExercise(aExercise, (_, result) => {
const es: Exercise[] = exerciseState.exercises.slice()
es.push({
name: aExercise.name, description: aExercise.description,
imagesJson: aExercise.imagesJson, major_muscles: selected,
push_or_pull: dropDownPushPullSelected
})
commonExercisesCRUD(es)
Toast.show("The exercise " + aExercise.name + " is created.")
})
}
function handleFilterExercises(keyword: string) {
console.log("handleFilterExercises")
setExerciseState({
...exerciseState,
filteredExercises:
exerciseState.exercises.filter(e => (
e.name.includes(keyword)
|| e.major_muscles.filter(
mm => mm.name.includes(keyword)
).length > 0
|| e.description.includes(keyword)
)),
filteredExerciseKeyword: keyword
})
}
//Scheduled Item Functions:
//renders:
function renderScheduledItemDialogForViewing(scheduledItem: ScheduledItem) {
textInputStyle = styles.textInputViewOnly
numberInputStyle = styles.numberInputViewOnly
setScheduledItemState({
...scheduledItemState,
aScheduledItem: scheduledItem
})
SetDialogState({
...dialogState,
isEditable: false, dialogText: ScheduledItemInformation,
isExDialogVisible: false, openPushPullDropDown: false,
isPlanDialogVisible: true
})
setDropDownExNameSelected(scheduledItem.exercise.name)
}
function commonLogicForScheduledItemEditAndDuplication(dialogText: string) {
textInputStyle = styles.textInputEditable
setScheduledItemState({ ...scheduledItemState, })
SetDialogState({
...dialogState, isEditable: true,
isDropDownOpen: false, dialogText: dialogText
})
setDropDownExNameSelected(scheduledItemState.aScheduledItem.exercise.name)
}
function renderScheduledItemDialogForCreate() {
textInputStyle = styles.textInputEditable
numberInputStyle = styles.numberInputEditable
setScheduledItemState({
...scheduledItemState,
aScheduledItem: initialScheduledItem[0]
})
SetDialogState({
...dialogState,
isEditable: true, dialogText: CreateScheduledItemText,
isPlanDialogVisible: true, isDropDownOpen: false,
})
setDropDownExNameSelected(exerciseState.exercises[0].name)
const parts: string[] = dialogState.planHeader.split(" ")[1].split("-")
const monthNumber: number = Number(parts[1])
const month: string = monthNumber < 10
? "0" + monthNumber.toString()
: monthNumber.toString()
const day: string = Number(parts[0]) < 10 ? "0" + parts[0] : parts[0]
const date: DateData = {
year: Number(parts[2]), month: monthNumber,
day: Number(parts[0]), timestamp: 0,
dateString: parts[2] + "-" + month + "-" + day
}
const aScheduledItem = initialScheduledItem[0]
aScheduledItem.date = date
setScheduledItemState({
...scheduledItemState,
aScheduledItem: { ...aScheduledItem }
})
}
//db:
function commonScheduledItemCRUD(si: ScheduledItem[]) {
setScheduledItemState({
...scheduledItemState, scheduledItems: [...si],
filteredScheduledItems: [...si],
selectedScheduledItems: [],
isMovingScheduledItems: false
})
cancelDialog()
}
const deleteScheduledItemConfirmation = (ms: ScheduledItem) => {
Alert.alert(
"Confirmation",
"Are you sure you want to delete this scheduled item?",
[{ text: "Yes", onPress: () => deleteScheduledItemWithStateUpdate(ms.id) },
{ text: "No", onPress: () => renderScheduledItemDialogForViewing(ms) }],//warning, recursive
{ cancelable: true }
)
}
const deleteScheduledItemWithStateUpdate = (id: number) => {
deleteScheduledItem(id, () => {
const si = scheduledItemState.scheduledItems.slice()
si.forEach((ms1, i) => {
if (ms1.id == id) {
si.splice(i, 1)
return
}
}) //correct way of removing element from a array for me. Not using delete keyword which leaves a undefined space
Toast.show("The scheduled item is deleted.")
commonScheduledItemCRUD(si)
})
}
const updateScheduledItemWithStateUpdate = () => {
const aScheduledItem = scheduledItemState.aScheduledItem
if (dropDownExNameSelected == undefined || dropDownExNameSelected == "") {
Toast.show("exercise must be selected")
return
}
const theexercise = exerciseState.exercises.filter((e, i, a) => {
if (e.name == dropDownExNameSelected) return e
})[0]
updateScheduledItem(aScheduledItem,
(_, result) => {
const toBeUpdated: ScheduledItem = {
id: aScheduledItem.id, exercise: theexercise, reps: aScheduledItem.reps,
percent_complete: aScheduledItem.percent_complete, sets: aScheduledItem.sets,
duration_in_seconds: aScheduledItem.duration_in_seconds,
weight: aScheduledItem.weight, notes: aScheduledItem.notes,
date: aScheduledItem.date
}
const ms: ScheduledItem[] = scheduledItemState.scheduledItems.slice()
ms.forEach((currentScheduledItem, i) => {
if (currentScheduledItem.id == aScheduledItem.id) {
ms.splice(i, 1, toBeUpdated)
return
}
})
commonScheduledItemCRUD(ms)
Toast.show("The major set is updated.")
},
)
}
function createScheduledItemWithStateUpdate() {
const aScheduledItem = scheduledItemState.aScheduledItem
exerciseState.exercises.forEach(e => {
if (e.name == dropDownExNameSelected) {
aScheduledItem.exercise = e
return
}
})
createScheduledItem(aScheduledItem,
(_, r) => {
const tempScheduledItem = { ...aScheduledItem }
tempScheduledItem.id = r.insertId!
tempScheduledItem.date = aScheduledItem.date
tempScheduledItem.duration_in_seconds = aScheduledItem.duration_in_seconds
const m = scheduledItemState.scheduledItems.slice()
m.push(tempScheduledItem)
commonScheduledItemCRUD(m)
Toast.show("Scheduled item created.")
})
}
function handleFilterScheduledItem(keyword: string) {
console.log("here")
const filtered = scheduledItemState.scheduledItems.filter(si => {
const sec = si.duration_in_seconds % 60
const min = Math.floor(si.duration_in_seconds / 60)
return ((si.percent_complete.toString() + "%").includes(keyword)
|| si.id.toString().includes(keyword)
|| (si.weight.toString() + "kg").includes(keyword)
|| (si.sets.toString() + "x" + si.reps.toString()).includes(keyword)
|| (min + " minutes").includes(keyword)
|| (sec + " seconds").includes(keyword)
|| si.exercise.name.includes(keyword)
|| si.exercise.major_muscles.filter(
si => si.name.includes(keyword)
).length > 0
)
}
)
setScheduledItemState({
...scheduledItemState,
filteredScheduledItems: filtered,
filteredScheduledItemKeyword: keyword
})
}
const buttonsSetProps: ButtonSetProps = {
cancelDialog: cancelDialog,
deleteScheduledItemConfirmation: deleteScheduledItemConfirmation,
deleteExerciseConfirmation: deleteExerciseConfirmation,
createExerciseWithStateUpdate: createExerciseWithStateUpdate,
updateExerciseWithStateUpdate: updateExerciseWithStateUpdate,
createScheduledItemWithStateUpdate: createScheduledItemWithStateUpdate,
updateScheduledItemWithStateUpdate: updateScheduledItemWithStateUpdate,
renderScheduledItemDialogForViewing: renderScheduledItemDialogForViewing,
renderScheduledItemDialogForDuplication:
() => commonLogicForScheduledItemEditAndDuplication(DuplicateScheduledItemText),
renderScheduledItemDialogForEdit:
() => commonLogicForScheduledItemEditAndDuplication(EditScheduledItemText),
renderExerciseDialogForEdit: renderExerciseDialogForEdit,
renderExerciseDialogForViewing: renderExerciseDialogForViewing,
}
const contextProps: ContextProps = {
renderScheduledItemDialogForViewing: renderScheduledItemDialogForViewing,
renderScheduledItemDialogForCreate: renderScheduledItemDialogForCreate,
renderExerciseDialogForCreate: renderExerciseDialogForCreate,
renderExerciseDialogForViewing: renderExerciseDialogForViewing,
handleFilterScheduledItem: handleFilterScheduledItem,
handlePlanHeader: handlePlanHeader,
handleFilterExercises: handleFilterExercises,
commonScheduledItemCRUD: commonScheduledItemCRUD,
scheduledItemState: scheduledItemState,
dialogState: dialogState,
exerciseState: exerciseState,
setDialogState: SetDialogState,
setScheduledItemState: setScheduledItemState,
setExerciseState: setExerciseState,
}
return (
<>
<NavigationContainer>
<ScheduleDialog
dialogState={dialogState}
exerciseState={exerciseState}
scheduledItemState={scheduledItemState}
dropDownExNameSelected={dropDownExNameSelected}
setScheduledItemState={setScheduledItemState}
setDialogState={SetDialogState}
setDropDownExNameSelected={setDropDownExNameSelected}
createExerciseWithStateUpdate={createExerciseWithStateUpdate}
updateExerciseWithStateUpdate={updateExerciseWithStateUpdate}
buttonsSetProps={buttonsSetProps}
/>
<ExerciseDialog
exerciseState={exerciseState}
dialogState={dialogState}
scheduledItemState={scheduledItemState}
majorMuscles={exerciseState.majorMuscles}
dropDownPushPullSelected={dropDownPushPullSelected}
dropDownMajorMuscleNameSelected={dropDownMajorMuscleNameSelected}
setDropDownPushPullSelected={setDropDownPushPullSelected}
setDialogState={SetDialogState}
setExerciseState={setExerciseState}
setMajorMuscleValues={setDropDownMajorMuscleValues}
buttonsSetProps={buttonsSetProps}
/>
<SelectDateDialog
scheduledItemState={scheduledItemState}
dialogState={dialogState}
setScheduledItemState={setScheduledItemState}
setDialogState={SetDialogState}
commonScheduledItemCRUD={commonScheduledItemCRUD}
buttonsSetProps={buttonsSetProps}
/>
<SettingsScreenContext.Provider value={{
handleResetDB: handleResetDB,
handleExport: handleExport,
handleImport: handleImport
}}>
<ExerciseScreenContext.Provider value={{ contextProps: contextProps }}>
<ScheduledItemContext.Provider value={{ contextProps: contextProps }}>
<Tab.Navigator
screenOptions={({ route }) =>
({
tabBarIcon: ({ focused, color, size }) => {
let iconName: any
switch (route.name) {
case 'Plan':
iconName = focused ? 'clipboard-list' : 'clipboard-list-outline'
return <MaterialCommunityIcons name={iconName} size={size} color={color} />
case 'Exercises':
iconName = focused ? 'arm-flex' : 'arm-flex-outline'
return <MaterialCommunityIcons name={iconName} size={size} color={color} />
case 'Settings':
iconName = focused ? 'settings' : 'settings-outline'
return <Ionicons name={iconName} size={size} color={color} />
}
},
tabBarActiveTintColor: Colors.light.tint
})
}>
<Tab.Screen
options={{ headerTitle: dialogState.planHeader }}
name="Plan" component={PlanScreen} />
<Tab.Screen name="Exercises" component={ExercisesScreen} />
<Tab.Screen name="Settings" component={SettingsScreen} />
</Tab.Navigator>
</ScheduledItemContext.Provider>
</ExerciseScreenContext.Provider>
</SettingsScreenContext.Provider>
</NavigationContainer >
</>
)
}
ExerciseScreen.tsx
import React from "react"
import { FlatList, Text, View, TouchableOpacity } from 'react-native'
import { ExerciseScreenContext } from '../constants/initialValues'
import { useContext } from 'react'
import layoutConstants from '../constants/Layout'
import { Exercise } from "../types"
import Layout from "../constants/Layout"
import Colors from "../constants/Colors"
import { TextInput } from "react-native"
import { Ionicons } from "@expo/vector-icons"
import { styles } from "../constants/styles"
function ExercisesScreen() {
let c = useContext(ExerciseScreenContext)
let filteredExercises: Exercise[] = c.contextProps.exerciseState.filteredExercises
let filteredKeyword: string = c.contextProps.exerciseState.filteredExerciseKeyword
let handleSelected: Function = c.contextProps.renderExerciseDialogForViewing
let handleShowCreate: Function = c.contextProps.renderExerciseDialogForCreate
let handleFilterExercises: Function = c.contextProps.handleFilterExercises
return (
<View style={{
flexDirection: "column", flex: 1,
alignItems: 'flex-start',
justifyContent: 'center'
}}>
<FlatList
style={{ width: '100%', transform: [{ rotateX: "180deg" }], }}
data={filteredExercises}
initialNumToRender={15}
renderItem={
({ item }) =>
<TouchableOpacity style={{
alignItems: "flex-start",
padding: layoutConstants.defaultMargin,
}}
onPress={() => handleSelected(item)}
>
<Text style={{
transform: [{ rotateX: "180deg" }],
fontSize: layoutConstants.defaultFontSize
}}>
{item.name}
</Text >
</TouchableOpacity>
}
/>
<TextInput
style={styles.filterExercisesTextInput}
placeholder="Type here to filter exercises..."
onChange={text => handleFilterExercises(text.nativeEvent.text)}
value={filteredKeyword}
/>
<View style={{ bottom: 20, end: 20, position: 'absolute' }}>
<TouchableOpacity
style={{
...styles.planScreenPressable,
backgroundColor: Colors.light.tint,
}}
onPress={() => handleShowCreate()}
>
<Ionicons style={{ bottom: "-5%", right: "-10%" }}
name="add-outline"
size={Layout.defaultMargin + 40} color="white" />
</TouchableOpacity>
</View>
</View>
)
}
export { ExercisesScreen }
Edit:
Link to my repo https://github.com/themissingCRAM/GymTracker
I guess i am not very clear in my question either the list of exercises should be there on my ExerciseScreen on startup but it isn't when I use my apk version only.
And my apologies, I am new to React and RN.