-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Description
📋 Overview
We need to implement a structured global state management system using Jotai atoms. This will help centralize and organize our application state in a type-safe, reactive way. The goal is to create domain-specific atom files that will manage different aspects of our application state.
🎯 Objective
Create a well-organized atoms directory structure with domain-specific atom files for managing global application state using Jotai's atomic state management pattern.
📁 Directory Structure to Create
apps/web/atoms/
├── user.ts # Authentication and user state
├── theme.ts # UI preferences and theming
├── settings.ts # Application configuration
└── index.ts # Clean re-exports
✅ Tasks
1. Create apps/web/atoms/user.ts
Implement atoms for user authentication and profile state:
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
// Primitive atoms (base state)
export const userAtom = atom<User | null>(null);
export const isAuthenticatedAtom = atom<boolean>(false);
export const authTokenAtom = atomWithStorage<string | null>('authToken', null);
// Derived atoms (computed values)
export const userDisplayNameAtom = atom(
(get) => get(userAtom)?.displayName || get(userAtom)?.email || 'Guest'
);
export const userInitialsAtom = atom((get) => {
const user = get(userAtom);
if (\!user) return 'G';
const name = user.displayName || user.email;
return name
.split(' ')
.map(n => n[0])
.join('')
.toUpperCase()
.slice(0, 2);
});
2. Create apps/web/atoms/theme.ts
Implement atoms for UI preferences and theming:
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
type Theme = 'light' | 'dark' | 'system';
type ColorScheme = 'blue' | 'green' | 'purple' | 'orange';
// Primitive atoms with localStorage persistence
export const themeAtom = atomWithStorage<Theme>('theme', 'system');
export const colorSchemeAtom = atomWithStorage<ColorScheme>('colorScheme', 'blue');
export const sidebarCollapsedAtom = atomWithStorage<boolean>('sidebarCollapsed', false);
// Derived atoms
export const resolvedThemeAtom = atom((get) => {
const theme = get(themeAtom);
if (theme \!== 'system') return theme;
// Check system preference
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
});
export const themeClassAtom = atom((get) => {
const theme = get(resolvedThemeAtom);
const color = get(colorSchemeAtom);
return `theme-${theme} color-${color}`;
});
3. Create apps/web/atoms/settings.ts
Implement atoms for application configuration:
import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils';
interface AppSettings {
notifications: {
email: boolean;
push: boolean;
sound: boolean;
};
privacy: {
shareAnalytics: boolean;
showOnlineStatus: boolean;
};
locale: string;
timezone: string;
}
// Default settings
const defaultSettings: AppSettings = {
notifications: {
email: true,
push: true,
sound: false,
},
privacy: {
shareAnalytics: false,
showOnlineStatus: true,
},
locale: 'en-US',
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};
// Primitive atom with localStorage persistence
export const settingsAtom = atomWithStorage<AppSettings>('appSettings', defaultSettings);
// Derived atoms for specific settings
export const notificationsEnabledAtom = atom(
(get) => {
const settings = get(settingsAtom);
return settings.notifications.email || settings.notifications.push;
}
);
export const localeAtom = atom(
(get) => get(settingsAtom).locale,
(get, set, locale: string) => {
const settings = get(settingsAtom);
set(settingsAtom, { ...settings, locale });
}
);
4. Create apps/web/atoms/index.ts
Create clean re-exports for all atoms:
// User atoms
export {
userAtom,
isAuthenticatedAtom,
authTokenAtom,
userDisplayNameAtom,
userInitialsAtom,
} from './user';
// Theme atoms
export {
themeAtom,
colorSchemeAtom,
sidebarCollapsedAtom,
resolvedThemeAtom,
themeClassAtom,
} from './theme';
// Settings atoms
export {
settingsAtom,
notificationsEnabledAtom,
localeAtom,
} from './settings';
💡 Implementation Tips
- Use TypeScript: Define proper types for all atom values
- Leverage atomWithStorage: Use this for values that should persist across sessions
- Create derived atoms: Use read-only atoms for computed values
- Keep atoms focused: Each atom should represent a single piece of state
- Use atom families: For dynamic collections of similar atoms (if needed)
📚 Example Usage in Components
import { useAtom, useAtomValue } from 'jotai';
import { userAtom, themeAtom, userDisplayNameAtom } from '@/atoms';
function UserProfile() {
const [user, setUser] = useAtom(userAtom);
const displayName = useAtomValue(userDisplayNameAtom);
const [theme, setTheme] = useAtom(themeAtom);
return (
<div>
<h1>Welcome, {displayName}\!</h1>
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
</div>
);
}
🧪 Testing Requirements
- Write unit tests for derived atoms logic
- Test localStorage persistence for atomWithStorage
- Verify atom updates trigger component re-renders
- Test edge cases (null users, invalid settings, etc.)
📖 Resources
- Existing store setup: Check
apps/web/lib/store.ts
for current Jotai configuration - Jotai Documentation: https://jotai.org/docs/core/atom
- Jotai Utils: https://jotai.org/docs/utilities/storage
- Best Practices: https://jotai.org/docs/guides/atoms-in-atom
⚡ Priority
High - This is foundational work that will improve state management across the entire application.
🎓 Good First Issue Notes
This is an excellent first issue because:
- Clear, well-defined scope
- Good introduction to our codebase structure
- Learn modern React state management patterns
- No complex business logic required
- Can be implemented incrementally
❓ Questions?
Feel free to ask questions in the comments! We're here to help you succeed with this contribution.
🔍 Definition of Done
- All atom files created with proper TypeScript types
- Atoms follow Jotai best practices
- Clean re-exports in index.ts
- Code follows project conventions (functional, modern TypeScript)
- Basic unit tests for derived atoms
- No ESLint warnings or TypeScript errors
Metadata
Metadata
Assignees
Labels
Type
Projects
Status