Replace react context with let statement in db.ts

1. I can't easily import context with my editor.
2. It's extra complexity everyone has to understand.
3. I hate the antichrist.
This commit is contained in:
Brandon Presley 2022-09-04 14:05:25 +12:00
parent 87b807336a
commit 607f83955d
16 changed files with 82 additions and 102 deletions

View File

@ -3,18 +3,17 @@ import {
useFocusEffect,
useNavigation,
} from '@react-navigation/native';
import React, {useCallback, useContext, useEffect, useState} from 'react';
import React, {useCallback, useEffect, useState} from 'react';
import {FlatList, StyleSheet, View} from 'react-native';
import {List, Searchbar} from 'react-native-paper';
import Best from './best';
import {BestPageParams} from './BestPage';
import {DatabaseContext} from './Routes';
import {db} from './db';
export default function BestList() {
const [bests, setBests] = useState<Best[]>([]);
const [search, setSearch] = useState('');
const [refreshing, setRefresing] = useState(false);
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<BestPageParams>>();
const refresh = useCallback(async () => {
@ -41,7 +40,7 @@ export default function BestList() {
newBest = newBest.concat(reps.rows.raw());
}
setBests(newBest);
}, [search, db]);
}, [search]);
useFocusEffect(
useCallback(() => {

View File

@ -5,8 +5,8 @@ import {FileSystem} from 'react-native-file-access';
import {Divider, IconButton, Menu} from 'react-native-paper';
import {DrawerParamList, SnackbarContext} from './App';
import ConfirmDialog from './ConfirmDialog';
import {db} from './db';
import {Plan} from './plan';
import {DatabaseContext} from './Routes';
import Set from './set';
import {write} from './write';
@ -16,7 +16,6 @@ const planFields = 'id,days,workouts';
export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
const [showMenu, setShowMenu] = useState(false);
const [showRemove, setShowRemove] = useState(false);
const db = useContext(DatabaseContext);
const {toast} = useContext(SnackbarContext);
const {reset} = useNavigation<NavigationProp<DrawerParamList>>();
@ -34,7 +33,7 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
.join('\n');
console.log(`${DrawerMenu.name}.exportSets`, {length: sets.length});
await write('sets.csv', data);
}, [db]);
}, []);
const exportPlans = useCallback(async () => {
const [result] = await db.executeSql('SELECT * FROM plans');
@ -45,7 +44,7 @@ export default function DrawerMenu({name}: {name: keyof DrawerParamList}) {
.join('\n');
console.log(`${DrawerMenu.name}.exportPlans`, {length: sets.length});
await write('plans.csv', data);
}, [db]);
}, []);
const download = useCallback(async () => {
setShowMenu(false);

View File

@ -5,13 +5,13 @@ import {
useNavigation,
useRoute,
} from '@react-navigation/native';
import React, {useCallback, useContext, useEffect, useState} from 'react';
import React, {useCallback, useEffect, useState} from 'react';
import {ScrollView, StyleSheet, Text, View} from 'react-native';
import {Button, IconButton} from 'react-native-paper';
import {DrawerParamList} from './App';
import {db} from './db';
import MassiveSwitch from './MassiveSwitch';
import {PlanPageParams} from './PlanPage';
import {DatabaseContext} from './Routes';
import {DAYS} from './time';
export default function EditPlan() {
@ -21,7 +21,6 @@ export default function EditPlan() {
params.plan.workouts.split(','),
);
const [names, setNames] = useState<string[]>([]);
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<DrawerParamList>>();
useFocusEffect(
@ -45,7 +44,7 @@ export default function EditPlan() {
setNames(namesResult.rows.raw().map(({name}) => name));
};
refresh();
}, [db]);
}, []);
const save = useCallback(async () => {
console.log(`${EditPlan.name}.save`, {days, workouts, params});
@ -63,7 +62,7 @@ export default function EditPlan() {
[newDays, newWorkouts, params.plan.id],
);
navigation.goBack();
}, [days, workouts, db, params, navigation]);
}, [days, workouts, params, navigation]);
const toggleWorkout = useCallback(
(on: boolean, name: string) => {

View File

@ -8,15 +8,14 @@ import React, {useCallback, useContext} from 'react';
import {NativeModules, View} from 'react-native';
import {IconButton} from 'react-native-paper';
import {SnackbarContext} from './App';
import {db} from './db';
import {HomePageParams} from './HomePage';
import {DatabaseContext} from './Routes';
import Set from './set';
import SetForm from './SetForm';
import Settings from './settings';
export default function EditSet() {
const {params} = useRoute<RouteProp<HomePageParams, 'EditSet'>>();
const db = useContext(DatabaseContext);
const navigation = useNavigation();
const {toast} = useContext(SnackbarContext);
@ -42,7 +41,7 @@ export default function EditSet() {
!!settings.vibrate,
settings.sound,
);
}, [db]);
}, []);
const update = useCallback(
async (set: Set) => {
@ -53,7 +52,7 @@ export default function EditSet() {
);
navigation.goBack();
},
[db, navigation],
[navigation],
);
const add = useCallback(
@ -75,7 +74,7 @@ export default function EditSet() {
toast("Great work King, that's a new record!", 3000);
navigation.goBack();
},
[db, navigation, startTimer, params.set, toast],
[navigation, startTimer, params.set, toast],
);
const save = useCallback(

View File

@ -4,20 +4,19 @@ import {
useNavigation,
useRoute,
} from '@react-navigation/native';
import React, {useCallback, useContext, useState} from 'react';
import React, {useCallback, useState} from 'react';
import {Image, ScrollView, View} from 'react-native';
import DocumentPicker from 'react-native-document-picker';
import {Button, IconButton} from 'react-native-paper';
import {set} from 'react-native-reanimated';
import {db} from './db';
import MassiveInput from './MassiveInput';
import {DatabaseContext} from './Routes';
import {WorkoutsPageParams} from './WorkoutsPage';
export default function EditWorkout() {
const [name, setName] = useState('');
const [uri, setUri] = useState('');
const {params} = useRoute<RouteProp<WorkoutsPageParams, 'EditWorkout'>>();
const db = useContext(DatabaseContext);
const navigation = useNavigation();
useFocusEffect(
@ -32,7 +31,7 @@ export default function EditWorkout() {
db.executeSql(`SELECT image FROM sets WHERE name = ? LIMIT 1`, [
params.value.name,
]).then(([result]) => setUri(result.rows.item(0)?.image));
}, [navigation, params.value.name, db]),
}, [navigation, params.value.name]),
);
const update = useCallback(async () => {
@ -54,7 +53,7 @@ export default function EditWorkout() {
params.value.name,
]);
navigation.goBack();
}, [db, navigation, params.value.name, name, uri]);
}, [navigation, params.value.name, name, uri]);
const add = useCallback(async () => {
const insert = `
@ -63,7 +62,7 @@ export default function EditWorkout() {
`;
await db.executeSql(insert, [name]);
navigation.goBack();
}, [db, navigation, name]);
}, [navigation, name]);
const save = useCallback(async () => {
if (params.value.name) return update();

View File

@ -1,10 +1,10 @@
import {NavigationProp, useNavigation} from '@react-navigation/native';
import React, {useCallback, useContext, useState} from 'react';
import React, {useCallback, useState} from 'react';
import {GestureResponderEvent} from 'react-native';
import {List, Menu} from 'react-native-paper';
import {db} from './db';
import {Plan} from './plan';
import {PlanPageParams} from './PlanPage';
import {DatabaseContext} from './Routes';
export default function PlanItem({
item,
@ -15,14 +15,13 @@ export default function PlanItem({
}) {
const [show, setShow] = useState(false);
const [anchor, setAnchor] = useState({x: 0, y: 0});
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<PlanPageParams>>();
const remove = useCallback(async () => {
await db.executeSql(`DELETE FROM plans WHERE id = ?`, [item.id]);
setShow(false);
onRemove();
}, [db, setShow, item.id, onRemove]);
}, [setShow, item.id, onRemove]);
const longPress = useCallback(
(e: GestureResponderEvent) => {

View File

@ -3,21 +3,20 @@ import {
useFocusEffect,
useNavigation,
} from '@react-navigation/native';
import React, {useCallback, useContext, useEffect, useState} from 'react';
import React, {useCallback, useEffect, useState} from 'react';
import {FlatList, StyleSheet, View} from 'react-native';
import {List, Searchbar} from 'react-native-paper';
import {db} from './db';
import DrawerMenu from './DrawerMenu';
import MassiveFab from './MassiveFab';
import {Plan} from './plan';
import PlanItem from './PlanItem';
import {PlanPageParams} from './PlanPage';
import {DatabaseContext} from './Routes';
export default function PlanList() {
const [search, setSearch] = useState('');
const [plans, setPlans] = useState<Plan[]>([]);
const [refreshing, setRefresing] = useState(false);
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<PlanPageParams>>();
const refresh = useCallback(async () => {
@ -29,7 +28,7 @@ export default function PlanList() {
db.executeSql(selectPlans, [`%${s}%`, `%${s}%`]);
const [plansResult] = await getPlans({s: search});
setPlans(plansResult.rows.raw());
}, [search, db]);
}, [search]);
useFocusEffect(
useCallback(() => {

View File

@ -1,10 +1,9 @@
import React, {useEffect, useState} from 'react';
import {useColorScheme} from 'react-native';
import {IconButton} from 'react-native-paper';
import {SQLiteDatabase} from 'react-native-sqlite-storage';
import {Drawer, DrawerParamList} from './App';
import BestPage from './BestPage';
import {getDb} from './db';
import {migrations} from './db';
import HomePage from './HomePage';
import PlanPage from './PlanPage';
import SettingsPage from './SettingsPage';
@ -16,17 +15,15 @@ interface Route {
icon: string;
}
export const DatabaseContext = React.createContext<SQLiteDatabase>(null as any);
export default function Routes() {
const [db, setDb] = useState<SQLiteDatabase | null>(null);
const [migrated, setMigrated] = useState(false);
const dark = useColorScheme() === 'dark';
useEffect(() => {
getDb().then(setDb);
migrations().then(() => setMigrated(true));
}, []);
if (!db) return null;
if (!migrated) return null;
const routes: Route[] = [
{name: 'Home', component: HomePage, icon: 'home'},
@ -37,27 +34,25 @@ export default function Routes() {
];
return (
<DatabaseContext.Provider value={db}>
<Drawer.Navigator
screenOptions={{
headerTintColor: dark ? 'white' : 'black',
swipeEdgeWidth: 1000,
}}>
{routes.map(route => (
<Drawer.Screen
key={route.name}
name={route.name}
component={route.component}
options={{
drawerIcon: ({focused}) => (
<IconButton
icon={focused ? route.icon : `${route.icon}-outline`}
/>
),
}}
/>
))}
</Drawer.Navigator>
</DatabaseContext.Provider>
<Drawer.Navigator
screenOptions={{
headerTintColor: dark ? 'white' : 'black',
swipeEdgeWidth: 1000,
}}>
{routes.map(route => (
<Drawer.Screen
key={route.name}
name={route.name}
component={route.component}
options={{
drawerIcon: ({focused}) => (
<IconButton
icon={focused ? route.icon : `${route.icon}-outline`}
/>
),
}}
/>
))}
</Drawer.Navigator>
);
}

View File

@ -1,8 +1,8 @@
import React, {useContext, useEffect, useRef, useState} from 'react';
import React, {useEffect, useRef, useState} from 'react';
import {ScrollView} from 'react-native';
import {Button, Text} from 'react-native-paper';
import {db} from './db';
import MassiveInput from './MassiveInput';
import {DatabaseContext} from './Routes';
import Set from './set';
export default function SetForm({
@ -25,7 +25,6 @@ export default function SetForm({
});
const weightRef = useRef<any>(null);
const repsRef = useRef<any>(null);
const db = useContext(DatabaseContext);
useEffect(() => {
console.log('SetForm.useEffect:', {uri, name: set.name});
@ -33,7 +32,7 @@ export default function SetForm({
db.executeSql(`SELECT image FROM sets WHERE name = ? LIMIT 1`, [
set.name,
]).then(([result]) => setUri(result.rows.item(0)?.image));
}, [uri, db, set.name]);
}, [uri, set.name]);
const handleSubmit = () => {
if (!name) return;

View File

@ -1,9 +1,9 @@
import {NavigationProp, useNavigation} from '@react-navigation/native';
import React, {useCallback, useContext, useState} from 'react';
import React, {useCallback, useState} from 'react';
import {GestureResponderEvent, Image} from 'react-native';
import {Divider, List, Menu, Text} from 'react-native-paper';
import {db} from './db';
import {HomePageParams} from './HomePage';
import {DatabaseContext} from './Routes';
import Set from './set';
export default function SetItem({
@ -23,14 +23,13 @@ export default function SetItem({
}) {
const [showMenu, setShowMenu] = useState(false);
const [anchor, setAnchor] = useState({x: 0, y: 0});
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<HomePageParams>>();
const remove = useCallback(async () => {
await db.executeSql(`DELETE FROM sets WHERE id = ?`, [item.id]);
setShowMenu(false);
onRemove();
}, [setShowMenu, db, onRemove, item.id]);
}, [setShowMenu, onRemove, item.id]);
const copy = useCallback(() => {
const set: Set = {...item};

View File

@ -3,14 +3,14 @@ import {
useFocusEffect,
useNavigation,
} from '@react-navigation/native';
import React, {useCallback, useContext, useEffect, useState} from 'react';
import React, {useCallback, useEffect, useState} from 'react';
import {FlatList, StyleSheet, View} from 'react-native';
import {List, Searchbar} from 'react-native-paper';
import {db} from './db';
import DrawerMenu from './DrawerMenu';
import {HomePageParams} from './HomePage';
import MassiveFab from './MassiveFab';
import {Plan} from './plan';
import {DatabaseContext} from './Routes';
import Set from './set';
import SetItem from './SetItem';
import Settings from './settings';
@ -35,7 +35,6 @@ export default function SetList() {
const [end, setEnd] = useState(false);
const [dates, setDates] = useState(false);
const [images, setImages] = useState(true);
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<HomePageParams>>();
const selectSets = `
@ -52,7 +51,7 @@ export default function SetList() {
setSets(result.rows.raw());
setOffset(0);
setEnd(false);
}, [search, db, selectSets]);
}, [search, selectSets]);
const refreshLoader = useCallback(async () => {
setRefreshing(true);

View File

@ -10,9 +10,9 @@ import DocumentPicker from 'react-native-document-picker';
import {Button, Searchbar, Text} from 'react-native-paper';
import {SnackbarContext} from './App';
import ConfirmDialog from './ConfirmDialog';
import {db} from './db';
import MassiveInput from './MassiveInput';
import MassiveSwitch from './MassiveSwitch';
import {DatabaseContext} from './Routes';
import Settings from './settings';
export default function SettingsPage() {
@ -28,7 +28,6 @@ export default function SettingsPage() {
const [battery, setBattery] = useState(false);
const [ignoring, setIgnoring] = useState(false);
const [search, setSearch] = useState('');
const db = useContext(DatabaseContext);
const {toast} = useContext(SnackbarContext);
const refresh = useCallback(async () => {
@ -45,7 +44,7 @@ export default function SettingsPage() {
setNotify(!!settings.notify);
setImages(!!settings.images);
NativeModules.AlarmModule.ignoringBattery(setIgnoring);
}, [db]);
}, []);
useEffect(() => {
refresh();
@ -75,7 +74,6 @@ export default function SettingsPage() {
predict,
sound,
notify,
db,
images,
]);

View File

@ -4,13 +4,7 @@ import {
useNavigation,
useRoute,
} from '@react-navigation/native';
import React, {
useCallback,
useContext,
useEffect,
useRef,
useState,
} from 'react';
import React, {useCallback, useEffect, useRef, useState} from 'react';
import {FileSystem} from 'react-native-file-access';
import {IconButton} from 'react-native-paper';
import RNPickerSelect from 'react-native-picker-select';
@ -18,7 +12,7 @@ import Share from 'react-native-share';
import ViewShot from 'react-native-view-shot';
import {BestPageParams} from './BestPage';
import Chart from './Chart';
import {DatabaseContext} from './Routes';
import {db} from './db';
import Set from './set';
import {formatMonth} from './time';
@ -46,7 +40,6 @@ export default function ViewBest() {
const [volumes, setVolumes] = useState<Volume[]>([]);
const [metric, setMetric] = useState(Metrics.Weight);
const [period, setPeriod] = useState(Periods.Monthly);
const db = useContext(DatabaseContext);
const navigation = useNavigation();
const viewShot = useRef<ViewShot>(null);
@ -97,7 +90,7 @@ export default function ViewBest() {
]);
if (result.rows.length === 0) return;
setWeights(result.rows.raw());
}, [params.best.name, db, period]);
}, [params.best.name, period]);
const refreshVolume = useCallback(async () => {
const select = `
@ -117,13 +110,13 @@ export default function ViewBest() {
]);
if (result.rows.length === 0) return;
setVolumes(result.rows.raw());
}, [db, params.best.name, period]);
}, [params.best.name, period]);
useEffect(() => {
if (metric === Metrics.Weight) refreshWeight();
else if (metric === Metrics.Volume) refreshVolume();
console.log(`${ViewBest.name}.useEffect`, {metric, period});
}, [params.best.name, db, metric, period, refreshVolume, refreshWeight]);
}, [params.best.name, metric, period, refreshVolume, refreshWeight]);
return (
<ViewShot style={{padding: 10}} ref={viewShot}>

View File

@ -1,9 +1,9 @@
import {NavigationProp, useNavigation} from '@react-navigation/native';
import React, {useCallback, useContext, useEffect, useState} from 'react';
import React, {useCallback, useEffect, useState} from 'react';
import {GestureResponderEvent, Image} from 'react-native';
import {List, Menu, Text} from 'react-native-paper';
import ConfirmDialog from './ConfirmDialog';
import {DatabaseContext} from './Routes';
import {db} from './db';
import Workout from './workout';
import {WorkoutsPageParams} from './WorkoutsPage';
@ -18,7 +18,6 @@ export default function WorkoutItem({
const [anchor, setAnchor] = useState({x: 0, y: 0});
const [showRemove, setShowRemove] = useState('');
const [uri, setUri] = useState('');
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<WorkoutsPageParams>>();
useEffect(() => {
@ -28,13 +27,13 @@ export default function WorkoutItem({
setUri(result.rows.item(0)?.image);
console.log(WorkoutItem.name, item.name, result.rows.item(0)?.image);
});
}, [db, item.name]);
}, [item.name]);
const remove = useCallback(async () => {
await db.executeSql(`DELETE FROM sets WHERE name = ?`, [item.name]);
setShowMenu(false);
onRemoved();
}, [setShowMenu, db, onRemoved, item.name]);
}, [setShowMenu, onRemoved, item.name]);
const longPress = useCallback(
(e: GestureResponderEvent) => {

View File

@ -3,11 +3,11 @@ import {
useFocusEffect,
useNavigation,
} from '@react-navigation/native';
import React, {useCallback, useContext, useEffect, useState} from 'react';
import React, {useCallback, useEffect, useState} from 'react';
import {FlatList, StyleSheet, View} from 'react-native';
import {List, Searchbar} from 'react-native-paper';
import {db} from './db';
import MassiveFab from './MassiveFab';
import {DatabaseContext} from './Routes';
import SetList from './SetList';
import Workout from './workout';
import WorkoutItem from './WorkoutItem';
@ -21,7 +21,6 @@ export default function WorkoutList() {
const [search, setSearch] = useState('');
const [refreshing, setRefreshing] = useState(false);
const [end, setEnd] = useState(false);
const db = useContext(DatabaseContext);
const navigation = useNavigation<NavigationProp<WorkoutsPageParams>>();
const select = `
@ -39,7 +38,7 @@ export default function WorkoutList() {
setWorkouts(result.rows.raw());
setOffset(0);
setEnd(false);
}, [search, db, select]);
}, [search, select]);
const refreshLoader = useCallback(async () => {
setRefreshing(true);
@ -81,7 +80,7 @@ export default function WorkoutList() {
setWorkouts([...workouts, ...result.rows.raw()]);
if (result.rows.length < limit) return setEnd(true);
setOffset(newOffset);
}, [search, end, offset, workouts, db, select]);
}, [search, end, offset, workouts, select]);
const onAdd = useCallback(async () => {
navigation.navigate('EditWorkout', {

12
db.ts
View File

@ -1,4 +1,8 @@
import {enablePromise, openDatabase} from 'react-native-sqlite-storage';
import {
enablePromise,
openDatabase,
SQLiteDatabase,
} from 'react-native-sqlite-storage';
enablePromise(true);
@ -67,8 +71,10 @@ const insertSettings = `
INSERT INTO settings(minutes) VALUES(3);
`;
export const getDb = async () => {
const db = await openDatabase({name: 'massive.db'});
export let db: SQLiteDatabase;
export const migrations = async () => {
db = await openDatabase({name: 'massive.db'});
await db.executeSql(createPlans);
await db.executeSql(createSets);
await db.executeSql(createSettings);