Skip to content

Instantly share code, notes, and snippets.

@azendal
Created September 5, 2024 23:23
Show Gist options
  • Save azendal/bafbbc550fb291077213edad340a78c6 to your computer and use it in GitHub Desktop.
Save azendal/bafbbc550fb291077213edad340a78c6 to your computer and use it in GitHub Desktop.
### 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