I am a beginner in react native and I am attempting to connect a save button in a modal header using expo-router
. I have managed to make the button work within the modal itself, but I would like it to be located in the header set by expo-router. It doesn't feel right to transfer the data-saving logic to the routing file, and even when I tried that, I encountered realm context errors. I am unsure of how to proceed. Is there a way to achieve this with expo? It seems like a common use case, but I haven't been able to find any examples, including in their documentation.
_layout.tsx
import React from 'react';
import { RealmProvider } from '@realm/react';
import { router, Stack } from 'expo-router';
import { HeaderButton } from '@components/common/fields/HeaderButton';
import { schemas } from '@models/index';
export default function Layout() {
return (
<RealmProvider schema={schemas} deleteRealmIfMigrationNeeded={true}>
<Stack>
<Stack.Screen
name="index"
options={{
headerShown: false,
}}
/>
<Stack.Screen
name="modal"
options={{
presentation: 'modal',
headerTitle: () => (
<HeaderButton displayText="<" handleClick={() => router.back()} />
),
// headerRight: () => (
// <HeaderButton
// handleClick={}
// displayText="Save"
// />
// ),
}}
/>
</Stack>
</RealmProvider>
);
}
modal.tsx
import React from 'react';
import { StatusBar } from 'expo-status-bar';
import { View } from 'react-native';
import { AddRecipeForm } from '@screens/recipe/AddRecipeForm';
export default function Modal() {
return (
<View>
<StatusBar style="light" />
<AddRecipeForm />
</View>
);
}
AddRecipeForm.tsx
import React, { useCallback } from 'react';
import { useRealm } from '@realm/react';
import { Controller, SubmitHandler, useForm } from 'react-hook-form';
import { StyleSheet, View } from 'react-native';
import { HeaderButton } from '@components/common/fields/HeaderButton';
import { TextField } from '@components/common/fields/TextField';
import { Recipe } from '@models/Recipe';
import colors from '@styles/colors';
interface AddRecipeFormProps {
userId?: string;
}
interface FormData {
userId?: string;
description: string;
name: string;
}
export const AddRecipeForm: React.FC<AddRecipeFormProps> = ({
// toggleModal,
userId,
}) => {
const { control, handleSubmit } = useForm<FormData>();
const realm = useRealm();
const handleAddRecipe = useCallback(
(name: string, description: string): void => {
if (!description && !name) {
return;
}
realm.write(() => {
return realm.create(Recipe, {
name,
description,
userId: userId ?? 'SYNC_DISABLED',
});
});
},
[realm, userId],
);
const onSubmit: SubmitHandler<FormData> = (data) => {
handleAddRecipe(data.name, data.description);
};
return (
<>
<View style={styles.container}>
<View style={styles.buttonContainer}>
<HeaderButton
displayText="Save"
handleClick={handleSubmit(onSubmit)}
/>
{/* <CustomButton displayText="Cancel" handleClick={toggleModal} /> */}
</View>
<Controller
control={control}
// rules={{ required: true }}
render={({ field: { onChange, value } }) => (
<TextField
value={value}
onChangeText={onChange}
placeholder="name"
/>
)}
name="name"
/>
<Controller
control={control}
// rules={{ required: true }}
render={({ field: { onChange, value } }) => (
<TextField
value={value}
onChangeText={onChange}
placeholder="description"
/>
)}
name="description"
/>
</View>
</>
);
};
tldr; Specifically, I want to relocate the HeaderButton
and its functionalities for usage in the modal header defined in the _layout.tsx
Stack. Moving all the logic out of the component into the layout doesn't seem ideal (and didn't work for me). Is there a way to achieve this?