many thank for your great reply. That help a lot. I could reproduce withoout error, but it does not as expected, may be because my lake of knowledge.
Here my steps.
First I renamed /hook/fieldContext.ts to /hook/filedProvider.tsx. I needed to add tsx to avoid error message at FieldContext.Provider
.
I copied your suggestion as the following
import React, { createContext, useState, ReactNode } from 'react';
type FieldContextType = {
field: string;
setField: (value: string) => void;
};
export const FieldContext = createContext<FieldContextType | undefined>(undefined);
export const FieldProvider = ({ children }: { children: ReactNode }) => {
const [field, setField] = useState("-1");
return (<FieldContext.Provider value={{ field, setField }}>
{children}
</FieldContext.Provider>);
};
Q1: I suppose, the above code is not a hook any more because of tsx. Should U move it to constants or components ?
Secondely: you asked to add <FieldProvider></FieldProvider>
at the root of my application, where is the navigation. I am confuse.
My app structure is as the following
app
- (tab)
-- map
--- layout.tsx
--- [id].tsx
-- settings
--- layout.tsx
--- setting.tsx
--- info.tsx
-- stations.tsx
-- index.tsx
-- alarms.tsx
-- layout.tsx
- layout.tsx
My navigation look like
app -layout.tsx
import { Stack } from "expo-router";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
const queryClient = new QueryClient
export default function Layout() {
return (
<QueryClientProvider client={queryClient}>
<Stack>
<Stack.Screen
name="(tabs)"
options={{
headerShown: false
}}
/>
<Stack.Screen
name="+not-found"
/*
options={{
headerShown: false,
}}
*/
/>
</Stack>
</QueryClientProvider>
);
}
and
app -(tab) --layout.tsx
I added <FieldProvider>
import FontAwesome from '@expo/vector-icons/FontAwesome6';
import { Tabs} from 'expo-router';
import { StyleSheet } from "react-native";
import { useThemeColors } from '@/hooks/useThemeColors';
import { useNavigation } from '@react-navigation/native';
import { useState } from "react";
import { FieldProvider } from '@/hooks/fieldProvider';
export default function TabLayout() {
const colors= useThemeColors()
const navigation = useNavigation();
const [sortKey, setSortKey] = useState<"id_station" | "station_name">("id_station")
return (
<FieldProvider>
<Tabs screenOptions={{ tabBarActiveTintColor: 'green'}}>
<Tabs.Screen
name="index"
options={{
headerShown: false,
title: 'Home',
headerStyle: {backgroundColor: colors.appHeadBackgroundColor, borderColor:'red'},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'normal',
},
tabBarIcon: ({ color }) => <FontAwesome size={28} name="arrows-to-circle" color={color} />,
tabBarStyle: {
display:'none',
backgroundColor: colors.appTabBarBackgroundColor,
paddingTop:8,
height:70,
}
}}
/>
<Tabs.Screen
name="map"
options={{
title: 'Map',
headerShown: false,
headerStyle: { backgroundColor: colors.appHeadBackgroundColor},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'normal',
},
tabBarIcon: ({ color }) => <FontAwesome size={28} name="map-location-dot" color={color} />,
//headerTitle: props => <LogoTitle />,
tabBarStyle: {
backgroundColor: colors.appTabBarBackgroundColor,
//paddingTop:8,
height:70,
}
}}
/>
<Tabs.Screen
name="station"
options={{
headerStyle: {
backgroundColor: colors.appHeadBackgroundColor
},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'normal',
},
headerShown: false,
href: null,
tabBarIcon: ({ color }) => <FontAwesome size={28} name="chart-line" color={color} />,
tabBarStyle: {
//backgroundColor: colors.appTabBarBackgroundColor,
//paddingTop:8,
height:70,
}
}}
/>
<Tabs.Screen
name="alarmes"
options={{
title: 'Alarmes',
headerShown: false,
headerStyle: { backgroundColor: colors.appHeadBackgroundColor},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'normal',
},
/*
headerRight: () => (
<Button onPress={() => router.back()}>Back</Button>
),
*/
tabBarIcon: ({ color }) => <FontAwesome size={28} name="bell" color={color} />,
//headerTitle: props => <LogoTitle />,
tabBarStyle: {
//backgroundColor: colors.appTabBarBackgroundColor,
//paddingTop:8,
height:70,
//borderWidth:30,
}
}}
/>
<Tabs.Screen
name="stations"
options={{
title: 'Stations',
headerShown: false,
headerStyle: { backgroundColor: colors.appHeadBackgroundColor},
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'normal',
},
tabBarIcon: ({ color }) => <FontAwesome size={28} name="map-pin" color={color} />,
tabBarStyle: {
//backgroundColor: colors.appTabBarBackgroundColor,
height:70,
}
}}
/>
<Tabs.Screen
name="settings"
options={{
title: 'Paramètres',
headerShown: false,
headerStyle: { backgroundColor: colors.appHeadBackgroundColor },
headerTintColor: '#000',
headerTitleStyle: {
fontWeight: 'normal',
},
/*
headerRight: () => (
<Button onPress={() => router.back()}>Back</Button>
),
*/
tabBarIcon: ({ color }) => <FontAwesome size={28} name="gear" color={color} />,
//headerTitle: props => <LogoTitle />,
tabBarStyle: {
backgroundColor: colors.appTabBarBackgroundColor,
//paddingTop:8,
height:70,
}
}}
/>
</Tabs>
</FieldProvider>
);
}
I was not really sure if it should go to at app/layout.tsx or at app/(tab)/layout.tsx (I tried both)
Problem: How can I get the value in my view settings.tsx and map.tsx. I tried the following in my view alert.tsx (it need it as well) as that viw is very simple at the moment.
Here is what I tried
import { Image, View } from "react-native";
import { useContext, useEffect, useState } from "react";
import { RootView } from "@/components/RootView";
import { ThemedText } from "@/components/ThemedText";
import { Row } from "@/components/Row";
import css from "@/hooks/styles";
import { useThemeColors } from "@/hooks/useThemeColors";
import AsyncStorage from '@react-native-async-storage/async-storage';
import { imagesHeader } from "@/components/imagesHeader";
import { FieldContext, FieldProvider } from "@/hooks/fieldProvider";
export default function Alarms() {
const colors = useThemeColors()
const field = useContext(FieldContext)
return(
<RootView>
<View style={[{backgroundColor: colors.appHeadBackgroundColor }]}>
<View style={css.jumbotronContainer}>
<Image
style={css.jumbotronImage}
source={imagesHeader.alarms.uri}
/>
</View>
</View>
<View style={css.container}>
<Row>
<ThemedText>Terrain sélectionner: </ThemedText>
<ThemedText>{field}</ThemedText>
</Row>
<ThemedText style={[css.text,css.paragraphe]}>Aucune station en alarme</ThemedText>
</View>
</RootView>
)
}
but {field}
does not print anything. It show an error.
and how my drop menu can update the value when the function
function onFieldChange(value:string) {
}
Many thanks for your help!!