Skip to content

Commit

Permalink
add redux integration
Browse files Browse the repository at this point in the history
  • Loading branch information
amarjanica committed Dec 11, 2024
1 parent 5dd4a2d commit 60eedfe
Show file tree
Hide file tree
Showing 15 changed files with 375 additions and 60 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,19 @@ Includes integration tests and a multi-platform demo (Android & web).
I made first version of the app to showcase how you can to database migrations
and configure integration tests to be run in a Node.js environment.
Read more about it in my blog post on [expo sqlite migrations and integration testing](https://www.amarjanica.com/bridging-the-gap-between-expo-sqlite-and-node-js/)
or [watch my YT tutorial](https://youtu.be/5OBi4JtlGfY).
or [watch my YT tutorial](https://youtu.be/5OBi4JtlGfY).
[Codebase](https://github.com/amarjanica/react-native-sqlite-expo-demo/tree/98c355d5b1fa065a5ec6585273232908edfe50ec)

## 2. Web support with SQLite, AsyncStorage and IndexedDB
I've added web support to the app, so it can run on the web. You can dynamically switch between
different storage types: SQLite, AsyncStorage and IndexedDB. SQLite is supported on the web via
[sql.js](https://github.com/sql-js/sql.js/).
Read more about it in my blog post on [expo sqlite, indexeddb and asyncstorage on the web](https://www.amarjanica.com/expo-sqlite-on-the-web-localstorage-indexeddb-and-sql-js/)
or [watch my YT tutorial](https://youtu.be/JZYXtOgqEbc).
or [watch my YT tutorial](https://youtu.be/JZYXtOgqEbc).
[Codebase](https://github.com/amarjanica/react-native-sqlite-expo-demo/tree/5dd4a2d046073127a1d9f82e7ebd54c1c1b98f7b)

## 3. Redux
I've integrated Redux into the app to manage global state more efficiently.

# App Screenshot
<p align="center">
Expand Down
22 changes: 12 additions & 10 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import React from 'react';
import AppDataProvider from '@/data/providers/AppDataProvider';
import { PersistenceType } from '@/data/types';

const enabledPersistenceTypes = Platform.select({
web: [PersistenceType.localstorage, PersistenceType.indexedDB, PersistenceType.sqlite],
default: [PersistenceType.localstorage, PersistenceType.sqlite],
});
const Root = () => {
const [persistenceType, setPersistenceType] = React.useState<PersistenceType>(
Platform.select({ web: PersistenceType.indexedDB, default: PersistenceType.sqlite })
Expand All @@ -20,15 +24,13 @@ const Root = () => {
Persistence type: {persistenceType}, OS: {Platform.OS}
</Text>
<View style={styles.buttons}>
<Button
title={PersistenceType.localstorage}
onPress={() => setPersistenceType(PersistenceType.localstorage)}></Button>
<Button
title={PersistenceType.indexedDB}
onPress={() => setPersistenceType(PersistenceType.indexedDB)}></Button>
<Button
title={PersistenceType.sqlite}
onPress={() => setPersistenceType(PersistenceType.sqlite)}></Button>
{enabledPersistenceTypes.map((persistenceType) => (
<Button
key={persistenceType}
title={persistenceType}
onPress={() => setPersistenceType(persistenceType)}
/>
))}
</View>
<Slot />
</AppDataProvider>
Expand All @@ -42,7 +44,7 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'space-around',
alignSelf: 'center',
width: '50%',
width: Platform.select({ web: '50%', default: '100%' }),
padding: 10,
},
container: {
Expand Down
19 changes: 6 additions & 13 deletions app/detail/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { router, useLocalSearchParams } from 'expo-router';
import React, { useState } from 'react';
import { Task } from '@/types';
import { Unmatched } from 'expo-router';
import { Button, StyleSheet, Text, View } from 'react-native';
import logger from '@/logger';
import { useDataContext } from '@/data/DataContext';
import { useAppDispatch, useAppSelector } from '@/store';
import { removeTaskHandler, selectTask } from '@/store/taskSlice';

const Page = () => {
const { id } = useLocalSearchParams<{ id: string }>();
const decodedId = parseInt(id);
const { tasksClient: client } = useDataContext();
const [task, setTask] = useState<Task | null>(null);
const { tasksClient } = useDataContext();
const [ready, setReady] = useState(false);
const dispatch = useAppDispatch();
const task = useAppSelector(selectTask(decodedId));

const goBack = () => {
if (router.canGoBack()) {
Expand All @@ -22,18 +23,10 @@ const Page = () => {
};

const handleDelete = async () => {
await client.delete(decodedId);
dispatch(removeTaskHandler({ tasksClient, id: decodedId }));
goBack();
};

React.useEffect(() => {
const prepare = async () => {
setTask(await client.task(decodedId));
};
logger.log('prepare detail');
prepare().finally(() => setReady(true));
}, [client, decodedId]);

if (!ready) {
return false;
}
Expand Down
19 changes: 6 additions & 13 deletions app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,21 @@ import type { ListRenderItem } from '@react-native/virtualized-lists';
import { router } from 'expo-router';
import globalStyles from '@/globalStyles';
import { useDataContext } from '@/data/DataContext';
import { useAppDispatch, useAppSelector } from '@/store';
import { addTaskHandler, selectTasksState } from '@/store/taskSlice';

const LandingPage = () => {
const { tasksClient: client } = useDataContext();
const [tasks, setTasks] = useState<Task[]>([]);
const { tasksClient } = useDataContext();
const dispatch = useAppDispatch();
const [newTask, setNewTask] = useState('');
const tasks = useAppSelector(selectTasksState);

const addTask = async () => {
if (newTask.trim()) {
await client.add(newTask.trim());
dispatch(addTaskHandler({ taskName: newTask, tasksClient }));
setNewTask('');
}
};
const prepareTasks = React.useCallback(async () => {
if (newTask.length === 0) {
logger.log('prepare tasks');
setTasks(await client.tasks());
}
}, [newTask]);

React.useEffect(() => {
void prepareTasks();
}, [prepareTasks]);

const renderItem: ListRenderItem<Task> = ({ item }) => (
<TouchableOpacity
Expand Down
Loading

0 comments on commit 60eedfe

Please sign in to comment.