This document explains the enhanced visualization component used in the NutriLens app.
The original FunctionalAIVisualization component had stability issues:
- Excessive re-renders when state was updated
- Race conditions with AsyncStorage updates
- Inconsistent state across mount/unmount cycles
- No central state management leading to data duplication
The new FunctionalAIVisualizationWithStore component uses Zustand for state management, providing:
- Global State: Consistent state accessible everywhere in the app
- Persistence: State persists across component mount/unmount cycles
- Performance: Reduced re-renders with selective state updates
- Stability: Better handling of race conditions
- Simpler interface: Cleaner API for updating visualization data
import FunctionalAIVisualizationWithStore from './FunctionalAIVisualizationWithStore';
import useVisualizationStore from '../store/useVisualizationStore';
// In your component:
const visualizationRef = useRef(null);
// You can directly update store state without needing the ref:
const store = useVisualizationStore();
store.updateWithSearchQueries(queries);
store.updateWithSearchResults(results);
store.updateWithFoodItems(items);
// Or use the ref if needed:
<FunctionalAIVisualizationWithStore
isDark={colorScheme === 'dark'}
isVisible={isLoading}
ref={visualizationRef}
onComplete={() => {}}
/>The Zustand store exposes these methods:
resetState(): Resets all state to initial valuessetStepState(step, state): Sets a step's state (active or completed)activateStep(step): Activates a step (and completes the previous)completeStep(step): Completes a stepupdateSubtitles(step, subtitles): Updates the subtitles for a stepupdateRealSubtitles(step, subtitles): Updates real subtitles for persistencesetDetectedFood(food): Updates detected foodupdateWithSearchQueries(queries): Updates with search queriesupdateWithSearchResults(results): Updates with search resultsupdateWithFoodItems(items): Updates with food itemssetAPIFinished(finished): Marks API as finishedgetCurrentSubtitle(step): Gets current subtitle for a stepcycleSubtitle(step): Cycles to next subtitleloadFromAsyncStorage(): Loads state from AsyncStorage
- The store centralizes all state that was previously scattered across the component
- AsyncStorage operations are abstracted away and handled by the store
- The component's UI is now purely presentational, with all logic in the store
- Atomic updates ensure state consistency
- All operations have better error handling and safety checks
- Seamless updates to the visualization as search data comes in
- No flickering or jumpy animations during updates
- Persisted state if user navigates away and back
- More responsive UI during heavy processing
- Better handling of edge cases (e.g., API finishes early)