An awesome Expo template with Jotai for state management and React Navigation for seamless navigation between screens.
- Node.js and npm installed
- Expo CLI installed (
npm install -g expo-cli
)
-
Clone the repository:
git clone https://github.com/your-username/expo-template-jotai.git cd expo-template-jotai
-
Install dependencies:
npm install
-
Start the development server:
npm start
project-root/
├── App.js
├── src/
│ ├── components/
│ ├── navigator/
│ │ └── Navigator.js
│ ├── store/
│ │ └── jotaiState.js
│ ├── hooks/
│ │ └── atomWithAsyncStorage.js
│ └── views/
│ ├── Home.js
│ └── ProfileScreen.js
│ └── ExampleComponent.js
To add a new screen to your Expo app, follow these steps:
-
Create the Screen Component: Create a new screen file in the
src/views/
directory. For example,ProfileScreen.js
:// src/views/ProfileScreen.js import React from 'react'; import { View, Text } from 'react-native'; const ProfileScreen = () => { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Profile Screen</Text> </View> ); }; export default ProfileScreen;
-
Add the Screen to the Navigator: Update
Navigator.js
to include the new screen:// src/navigator/Navigator.js import React from 'react'; import { NavigationContainer } from '@react-navigation/native'; import { createStackNavigator } from '@react-navigation/stack'; import Home from '../views/Home'; import ExampleComponent from '../views/ExampleComponent'; import ProfileScreen from '../views/ProfileScreen'; const Stack = createStackNavigator(); const Navigator = () => { return ( <NavigationContainer> <Stack.Navigator initialRouteName="Home"> <Stack.Screen name="Home" component={Home} /> <Stack.Screen name="Example" component={ExampleComponent} /> <Stack.Screen name="Profile" component={ProfileScreen} /> </Stack.Navigator> </NavigationContainer> ); }; export default Navigator;
-
Navigate to the New Screen: Update
Home.js
to navigate to the newProfileScreen
:// src/views/Home.js import React from 'react'; import { View, Text, Button } from 'react-native'; import { useAtom } from 'jotai'; import { homeCountAtom } from '../store/jotaiState'; const Home = ({ navigation }) => { const [count, setCount] = useAtom(homeCountAtom); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>{count}</Text> <Button title="Increment" onPress={() => setCount(count + 1)} /> <Button title="Go to Example Component" onPress={() => navigation.navigate('Example')} /> <Button title="Go to Profile" onPress={() => navigation.navigate('Profile')} /> </View> ); }; export default Home;
-
Define a Simple State Atom: Define a simple state atom in
jotaiState.js
:// src/store/jotaiState.js import { atomWithAsyncStorage } from '../utils/atomWithAsyncStorage'; export const homeCountAtom = atomWithAsyncStorage('homeCount', 0); export const exampleCountAtom = atomWithAsyncStorage('exampleCount', 0); export const userNameAtom = atomWithAsyncStorage('userName', '');
-
Use the Simple Atom in a Component: Use the simple atom in a component, for example,
ProfileScreen.js
:// src/views/ProfileScreen.js import React from 'react'; import { View, Text, TextInput } from 'react-native'; import { useAtom } from 'jotai'; import { userNameAtom } from '../store/jotaiState'; const ProfileScreen = () => { const [userName, setUserName] = useAtom(userNameAtom); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Profile Screen</Text> <TextInput value={userName} onChangeText={setUserName} placeholder="Enter your name" style={{ borderWidth: 1, borderColor: 'gray', margin: 10, padding: 5, width: 200 }} /> </View> ); }; export default ProfileScreen;
-
Define a Complex State Atom: Define a complex state atom in
jotaiState.js
:// src/store/jotaiState.js import { atomWithAsyncStorage } from '../utils/atomWithAsyncStorage'; export const homeCountAtom = atomWithAsyncStorage('homeCount', 0); export const exampleCountAtom = atomWithAsyncStorage('exampleCount', 0); export const userNameAtom = atomWithAsyncStorage('userName', ''); // Define a complex atom export const userSettingsAtom = atomWithAsyncStorage('userSettings', { theme: 'light', notifications: true, notes: '' });
-
Use the Complex Atom in a Component: Use the complex atom in a component, for example,
ProfileScreen.js
:// src/views/ProfileScreen.js import React from 'react'; import { View, Text, Button, TextInput } from 'react-native'; import { useAtom } from 'jotai'; import { userSettingsAtom } from '../store/jotaiState'; const ProfileScreen = () => { const [userSettings, setUserSettings] = useAtom(userSettingsAtom); return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>Profile Screen</Text> <Button title={`Toggle Theme (Current: ${userSettings.theme})`} onPress={() => setUserSettings({ ...userSettings, theme: userSettings.theme === 'light' ? 'dark' : 'light' }) } /> <Text>Notifications: {userSettings.notifications ? 'On' : 'Off'}</Text> <Button title="Toggle Notifications" onPress={() => setUserSettings({ ...userSettings, notifications: !userSettings.notifications }) } /> <Text>Notes: {userSettings.notes}</Text> <TextInput value={userSettings.notes} onChangeText={(text) => setUserSettings({ ...userSettings, notes: text }) } placeholder="Enter notes" style={{ borderWidth: 1, borderColor: 'gray', margin: 10, padding: 5, width: 200 }} /> </View> ); }; export default ProfileScreen;
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.