slogan3

Ontwikkel een React Native-app met geavanceerde dependency injection en modulaire architectuur

description

Maakt het mogelijk om een schone, schaalbare en onderhoudbare React Native-app te bouwen door componenten te ontkoppelen en afhankelijkheden efficiënt te beheren. Verbetert testbaarheid en faciliteert toekomstige uitbreiding van functies, waardoor een robuuste basis ontstaat vergeleken met monolithische ontwerpen.

prompt

Help me bij het ontwerpen en implementeren van een modulaire architectuur voor mijn React Native-app met behulp van dependency injection technieken. Leg uit hoe ik mijn app-componenten, services en utilities kan structureren om a ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht en stappenplan om een modulaire architectuur met dependency injection (DI) voor je React Native e-commerce app te implementeren, zodat je afhankelijkheden losser worden gekoppeld, testen eenvoudiger worden en schaalbaarheid verbetert. ### 1. **Architectuurprincipes en doelen** - **Modulariteit:** Scheid UI, bedrijfslogica, services en utilities. - **Dependency Injection:** Beheer afhankelijkheden centraal, zodat componenten niet direct nieuwe instanties maken. - **Testbaarheid:** Maak het mogelijk om gemakkelijk te mocken of stubben tijdens testen. - **Schaalbaarheid:** Voeg nieuwe features toe zonder de bestaande code te breken. --- ### 2. **Structuur opzetten** **a. Mapstructuur voorbeeld** ``` /src /components // UI-componenten /screens // Pagina’s of views /services // Business- en API-services /utils // Hulpfuncties en utilities /di // Dependency injection configuraties /models // Data modellen /navigation // Navigatie setup ``` --- ### 3. **Dependency Injection aanpak** **a. Service container maken** Gebruik een eenvoudige DI container, bijvoorbeeld met een singleton object dat alle dependencies beheert. ```js // src/di/Container.js class Container { constructor() { this.dependencies = {}; } register(key, instance) { this.dependencies[key] = instance; } get(key) { return this.dependencies[key]; } } const container = new Container(); export default container; ``` **b. Services registreren** Bij het starten van je app, registreer je je services: ```js // src/di/setup.js import container from './Container'; import ApiService from '../services/ApiService'; import CartService from '../services/CartService'; // Instantiate en registreer services const apiService = new ApiService(); const cartService = new CartService(apiService); container.register('ApiService', apiService); container.register('CartService', cartService); ``` **c. Services gebruiken in componenten** In je React componenten haal je dependencies op via de container: ```js import React, { useEffect, useState } from 'react'; import container from '../di/Container'; const ProductListScreen = () => { const apiService = container.get('ApiService'); const [products, setProducts] = useState([]); useEffect(() => { apiService.fetchProducts().then(setProducts); }, []); // UI rendering... }; ``` --- ### 4. **Services en utilities structureren** - **Services:** Bevatten API calls, bedrijfslogica, etc. - **Utilities:** Algemene helper functies, formatteringsfuncties, etc. Voorbeeld: ```js // src/services/ApiService.js class ApiService { fetchProducts() { // API call implementatie } } export default ApiService; ``` --- ### 5. **Testen en mocking** Omdat je afhankelijkheden via DI worden beheerd, kun je tijdens testen je dependencies mocken: ```js const mockApiService = { fetchProducts: () => Promise.resolve([/* mock data */]), }; // In test setup container.register('ApiService', mockApiService); ``` Zo test je je componenten zonder echte API calls. --- ### 6. **Voordelen van deze aanpak** - **Losse koppeling:** UI-componenten en services zijn niet direct afhankelijk van concrete implementaties. - **Gemakkelijk testen:** Mock dependencies eenvoudig injecteren. - **Uitbreidbaarheid:** Nieuwe services toevoegen zonder bestaande code te veranderen. - **Schaalbaarheid:** Modulariseer verder door features in aparte modules te plaatsen. --- ### 7. **Aanvullende tips** - Overweeg een Dependency Injection library zoals `inversify` voor complexere scenarios. - Gebruik Context API of React's `useContext` voor dependency provision op hoger niveau. - Combineer DI met een goede architectuur (bv. MVVM of Clean Architecture) voor nog betere scheiding. --- ### Samenvatting Door een centrale DI container te gebruiken, registreer je je services en utilities en haal je ze op in je componenten. Dit vermindert de koppeling, verbetert testbaarheid en maakt je app beter schaalbaar. --- Wil je een concreet voorbeeld van een volledige setup of hulp bij het integreren in jouw bestaande project?
provider: deepseek
model: deepseek-chat
Zeker! Ik help je bij het ontwerpen van een modulaire architectuur voor je React Native e-commerce app met dependency injection. Hier is een complete aanpak: ## 1. Architectuur Overzicht ``` src/ ├── core/ # Kern functionaliteit ├── modules/ # Feature modules ├── shared/ # Gedeelde componenten/services ├── infrastructure/ # Externe dependencies └── app/ # App configuratie & dependency setup ``` ## 2. Dependency Injection Container ```typescript // src/core/di/container.ts interface DIContainer { register<T>(token: string, provider: T): void; resolve<T>(token: string): T; } class Container implements DIContainer { private providers = new Map<string, any>(); register<T>(token: string, provider: T): void { this.providers.set(token, provider); } resolve<T>(token: string): T { const provider = this.providers.get(token); if (!provider) { throw new Error(`Provider niet gevonden: ${token}`); } return provider; } } export const container = new Container(); ``` ## 3. Service Interfaces & Implementaties ```typescript // src/core/interfaces/IProductService.ts export interface IProductService { getProducts(): Promise<Product[]>; getProductById(id: string): Promise<Product>; searchProducts(query: string): Promise<Product[]>; } // src/modules/products/services/ProductService.ts export class ProductService implements IProductService { constructor(private apiClient: IApiClient) {} async getProducts(): Promise<Product[]> { return this.apiClient.get('/products'); } async getProductById(id: string): Promise<Product> { return this.apiClient.get(`/products/${id}`); } async searchProducts(query: string): Promise<Product[]> { return this.apiClient.get(`/products/search?q=${query}`); } } ``` ## 4. Module Structuur ```typescript // src/modules/products/index.ts export { ProductList } from './components/ProductList'; export { ProductDetail } from './components/ProductDetail'; export { ProductService } from './services/ProductService'; export type { IProductService } from '../../core/interfaces/IProductService'; // src/modules/cart/index.ts export { Cart } from './components/Cart'; export { CartService } from './services/CartService'; ``` ## 5. Component met Dependency Injection ```typescript // src/modules/products/components/ProductList.tsx import React, { useEffect, useState } from 'react'; import { container } from '../../../core/di/container'; import { IProductService } from '../../../core/interfaces/IProductService'; export const ProductList: React.FC = () => { const [products, setProducts] = useState<Product[]>([]); const [loading, setLoading] = useState(true); // Dependency injection via container const productService = container.resolve<IProductService>('ProductService'); useEffect(() => { loadProducts(); }, []); const loadProducts = async () => { try { const productsData = await productService.getProducts(); setProducts(productsData); } catch (error) { console.error('Fout bij laden producten:', error); } finally { setLoading(false); } }; if (loading) return <LoadingSpinner />; return ( <View> {products.map(product => ( <ProductCard key={product.id} product={product} /> ))} </View> ); }; ``` ## 6. Dependency Setup ```typescript // src/app/dependencies.ts import { container } from '../core/di/container'; import { ProductService } from '../modules/products/services/ProductService'; import { CartService } from '../modules/cart/services/CartService'; import { ApiClient } from '../infrastructure/api/ApiClient'; import { IProductService } from '../core/interfaces/IProductService'; import { ICartService } from '../core/interfaces/ICartService'; export const setupDependencies = () => { // Infrastructure dependencies const apiClient = new ApiClient(); container.register('ApiClient', apiClient); // Service dependencies const productService = new ProductService(apiClient); const cartService = new CartService(apiClient); container.register<IProductService>('ProductService', productService); container.register<ICartService>('CartService', cartService); }; ``` ## 7. Testbare Componenten ```typescript // src/modules/products/components/__tests__/ProductList.test.tsx import React from 'react'; import { render, waitFor } from '@testing-library/react-native'; import { ProductList } from '../ProductList'; import { IProductService } from '../../../../core/interfaces/IProductService'; import { container } from '../../../../core/di/container'; // Mock service const mockProductService: IProductService = { getProducts: jest.fn().mockResolvedValue([ { id: '1', name: 'Test Product', price: 99.99 } ]), getProductById: jest.fn(), searchProducts: jest.fn() }; describe('ProductList', () => { beforeEach(() => { container.register<IProductService>('ProductService', mockProductService); }); afterEach(() => { container.register<IProductService>('ProductService', mockProductService); }); it('laadt en toont producten', async () => { const { getByText } = render(<ProductList />); await waitFor(() => { expect(getByText('Test Product')).toBeTruthy(); }); expect(mockProductService.getProducts).toHaveBeenCalledTimes(1); }); }); ``` ## 8. Service Test ```typescript // src/modules/products/services/__tests__/ProductService.test.ts import { ProductService } from '../ProductService'; import { IApiClient } from '../../../../core/interfaces/IApiClient'; describe('ProductService', () => { let productService: ProductService; let mockApiClient: jest.Mocked<IApiClient>; beforeEach(() => { mockApiClient = { get: jest.fn(), post: jest.fn(), put: jest.fn(), delete: jest.fn() }; productService = new ProductService(mockApiClient); }); it('haalt producten op via API client', async () => { const mockProducts = [{ id: '1', name: 'Test Product' }]; mockApiClient.get.mockResolvedValue(mockProducts); const result = await productService.getProducts(); expect(mockApiClient.get).toHaveBeenCalledWith('/products'); expect(result).toEqual(mockProducts); }); }); ``` ## 9. App Configuratie ```typescript // App.tsx import React from 'react'; import { setupDependencies } from './src/app/dependencies'; import { ProductList } from './src/modules/products'; import { Cart } from './src/modules/cart'; // Dependency injection setup setupDependencies(); const App: React.FC = () => { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Products" component={ProductList} /> <Stack.Screen name="Cart" component={Cart} /> </Stack.Navigator> </NavigationContainer> ); }; export default App; ``` ## 10. Voordelen van deze Architectuur ### 🎯 **Testbaarheid** - Services kunnen gemakkelijk gemockt worden - Componenten zijn geïsoleerd testbaar - Business logic is gescheiden van UI ### 🔄 **Schaalbaarheid** - Nieuwe features als aparte modules toevoegen - Eenvoudige vervanging van implementaties - Duidelijke verantwoordelijkheden ### 🛠 **Onderhoud** - Minder coupled code - Betere code organisation - Eenvoudigere debugging ### 🚀 **Development Experience** - Snellere feature development - Betere team collaboration - Eenvoudigere onboarding nieuwe developers Deze architectuur zorgt voor een solide foundation voor je e-commerce app met uitstekende testbaarheid en schaalbaarheid!