Created
September 5, 2024 23:23
-
-
Save azendal/bafbbc550fb291077213edad340a78c6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Step-by-Step Full Implementation | |
#### 1. Install `react-native-config` | |
First, install the `react-native-config` package: | |
```bash | |
npm install react-native-config | |
npx react-native link react-native-config | |
``` | |
#### 2. Create Environment Files | |
Create two environment files to distinguish between the REST and GraphQL backends. | |
**.env.rest** | |
```env | |
BACKEND_TYPE=rest | |
API_URL=https://rest-api.com | |
``` | |
**.env.graphql** | |
```env | |
BACKEND_TYPE=graphql | |
API_URL=https://graphql-api.com/graphql | |
``` | |
#### 3. Implement Backend Interfaces | |
Create a generic interface that both REST and GraphQL services will implement. | |
**src/services/BackendService.ts** | |
```ts | |
export interface BackendService { | |
fetchData: (endpointOrQuery: string, paramsOrVariables?: any) => Promise<any>; | |
sendData: (endpointOrMutation: string, dataOrVariables: any) => Promise<any>; | |
} | |
``` | |
#### 4. Implement REST and GraphQL Services | |
Implement the REST and GraphQL service classes that conform to the `BackendService` interface. | |
**src/services/RestService.ts** | |
```ts | |
import { BackendService } from './BackendService'; | |
import Config from 'react-native-config'; | |
export class RestService implements BackendService { | |
async fetchData(endpoint: string, params?: any): Promise<any> { | |
const response = await fetch(`${Config.API_URL}/${endpoint}`, { | |
method: 'GET', | |
}); | |
return response.json(); | |
} | |
async sendData(endpoint: string, data: any): Promise<any> { | |
const response = await fetch(`${Config.API_URL}/${endpoint}`, { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify(data), | |
}); | |
return response.json(); | |
} | |
} | |
``` | |
**src/services/GraphqlService.ts** | |
```ts | |
import { BackendService } from './BackendService'; | |
import Config from 'react-native-config'; | |
export class GraphqlService implements BackendService { | |
async fetchData(query: string, variables?: any): Promise<any> { | |
const response = await fetch(Config.API_URL, { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ query, variables }), | |
}); | |
return response.json(); | |
} | |
async sendData(mutation: string, variables: any): Promise<any> { | |
const response = await fetch(Config.API_URL, { | |
method: 'POST', | |
headers: { 'Content-Type': 'application/json' }, | |
body: JSON.stringify({ mutation, variables }), | |
}); | |
return response.json(); | |
} | |
} | |
``` | |
#### 5. Create Backend Loader for Dynamic Imports | |
Create a loader to dynamically import the appropriate backend service based on the environment variable. | |
**src/BackendLoader.ts** | |
```ts | |
import Config from 'react-native-config'; | |
export const loadBackendService = async () => { | |
if (Config.BACKEND_TYPE === 'rest') { | |
const { RestService } = await import('./services/RestService'); | |
return new RestService(); | |
} else if (Config.BACKEND_TYPE === 'graphql') { | |
const { GraphqlService } = await import('./services/GraphqlService'); | |
return new GraphqlService(); | |
} else { | |
throw new Error('Unknown BACKEND_TYPE in environment'); | |
} | |
}; | |
``` | |
#### 6. Create Context for Backend Service | |
Create a React context to provide the backend service throughout your app. | |
**src/context/BackendContext.tsx** | |
```ts | |
import React, { createContext, useContext, ReactNode } from 'react'; | |
import { BackendService } from '../services/BackendService'; | |
const BackendContext = createContext<BackendService | null>(null); | |
export const BackendProvider = ({ | |
service, | |
children, | |
}: { | |
service: BackendService; | |
children: ReactNode; | |
}) => { | |
return ( | |
<BackendContext.Provider value={service}> | |
{children} | |
</BackendContext.Provider> | |
); | |
}; | |
export const useBackend = (): BackendService => { | |
const context = useContext(BackendContext); | |
if (!context) { | |
throw new Error('useBackend must be used within a BackendProvider'); | |
} | |
return context; | |
}; | |
``` | |
#### 7. Modify the Main App Component to Load the Service | |
Modify your main `App.tsx` file to dynamically load the backend service based on the environment variable. | |
**App.tsx** | |
```tsx | |
import React, { useEffect, useState } from 'react'; | |
import { BackendProvider } from './context/BackendContext'; | |
import { MainComponent } from './components/MainComponent'; | |
import { loadBackendService } from './BackendLoader'; | |
const App = () => { | |
const [backendService, setBackendService] = useState<any>(null); | |
const [loading, setLoading] = useState(true); | |
useEffect(() => { | |
const loadService = async () => { | |
const service = await loadBackendService(); | |
setBackendService(service); | |
setLoading(false); | |
}; | |
loadService(); | |
}, []); | |
if (loading) { | |
return <div>Loading...</div>; | |
} | |
return ( | |
<BackendProvider service={backendService}> | |
<MainComponent /> | |
</BackendProvider> | |
); | |
}; | |
export default App; | |
``` | |
#### 8. Access Backend Service in Components | |
Now, in your components, you can access the backend service via the `useBackend` hook. | |
**src/components/MainComponent.tsx** | |
```tsx | |
import React, { useEffect, useState } from 'react'; | |
import { useBackend } from '../context/BackendContext'; | |
export const MainComponent = () => { | |
const backend = useBackend(); | |
const [data, setData] = useState<any>(null); | |
useEffect(() => { | |
// Fetch data from the current backend (REST or GraphQL) | |
backend.fetchData('some-endpoint-or-query').then(setData); | |
}, [backend]); | |
return ( | |
<div> | |
{data ? <div>{JSON.stringify(data)}</div> : <div>Loading data...</div>} | |
</div> | |
); | |
}; | |
``` | |
#### 9. Add Build Scripts for Different Environments | |
To differentiate between the environments when building the app, you can create build scripts for each environment. | |
In your `package.json`, add these scripts: | |
```json | |
"scripts": { | |
"start-rest": "BACKEND_ENV=rest react-native start", | |
"start-graphql": "BACKEND_ENV=graphql react-native start", | |
"android-rest": "BACKEND_ENV=rest react-native run-android", | |
"android-graphql": "BACKEND_ENV=graphql react-native run-android", | |
"ios-rest": "BACKEND_ENV=rest react-native run-ios", | |
"ios-graphql": "BACKEND_ENV=graphql react-native run-ios" | |
} | |
``` | |
These scripts will load the correct `.env` file for REST or GraphQL based on the `BACKEND_ENV` variable. | |
To build for REST: | |
```bash | |
npm run start-rest | |
npm run android-rest | |
npm run ios-rest | |
``` | |
To build for GraphQL: | |
```bash | |
npm run start-graphql | |
npm run android-graphql | |
npm run ios-graphql | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment