Ben Phung
Ben Phung

Reputation: 346

How to use class service in React Native

I come from the Angular world where I can have a service with methods and properties. Then I can import this class in another file, inject it in the constructor and call the class's members. Now I am working on a mobile app with React Native and Expo. I am wondering if I can do the same dependency injection.

This is what I have so far:

// HttpService.ts

import....

export default class HttpService{
  private field = "";
  public method1 = () => {}
  public method2 = () => {}
  private otherMethod = () => {}
}

Usage from Component:

// MakeApiCall.tsx
import HttpService from "./services/HttpService";
     
export...
// HttpService.method1 is not available.

I don't want to new up an instance of HttpService every time I call the class's members.

Upvotes: 2

Views: 3991

Answers (3)

guy.gc
guy.gc

Reputation: 3501

You can use Obsidian to inject hooks and components. It's a dependency injection library for React Native.

You basically declare you dependencies in a graph, then inject components or hooks from those graphs.

  1. First, declare the HttpService in a graph.
import {Singleton, Graph, ObjectGraph, Provides} from 'react-obsidian';


@Singleton() @Graph()
export class ApplicationGraph extends ObjectGraph {

  @Provides()
  http(): HttpService {
    return new HttpService();
  }
}
  1. Inject your hook
import {DependenciesOf, injectHook} from 'react-obsidian';
import {ApplicationGraph} from './ApplicationGraph';

// 1. Declare which dependencies should be injected.
type Injected = DependenciesOf<ApplicationGraph, 'http'>; // {http: HttpService}

// 2. Implement the hook.
const myHook = ({http}: Injected) => {
  // Do something with the Http service
}

// 3. Export the injected hook.
export default injectHook(myHook, ApplicationGraph);
  1. When using the hook, you don't need to pass anything to it. The dependencies are resolved automatically.

Upvotes: 0

Jim Buck
Jim Buck

Reputation: 2444

Coming from Angular there is a change in how data and components interact. Rather than injecting a service React favors small composable functions in the form of hooks. They can seem pretty complex at first, but they are very nice to work with once you learn them.

In short, rather than create an HTTP service you would probably be better off creating a hook for each method, using a tested fetch framework. Hooks can be tested independently and can share logic, like so:

import useFetch from 'react-fetch-hook';

export function useMethod1() {
  return useFetch('/api/data1');
}

export function useMethod2() {
  return useFetch('/api/data2');
}
// Usage

import {useMethod1, useMethod2} from '../hooks/data';

export function Display() {

  const { isLoading, data, error } = useMethod1();

  if (error) return <p>{{error}}</p>;

  if (isLoading) return <p>Loading...</p>;

  return <ul>{{data.map(d => (<li>{{d}}</li>))}}</ul>;

}

If you are set on using services, then this article by LogRocket might help address the use case you are working with.

Upvotes: 2

emeraldsanto
emeraldsanto

Reputation: 4741

You can export a singleton instance of that class:

// HttpService.ts
import....

class HttpService {
  private field = "";
  public method1 = () => {}
  public method2 = () => {}
  private otherMethod = () => {}
}

const singleton = new HttpService();
export default singleton;
// MakeApiCall.tsx
import HttpService from "./services/HttpService";
     
HttpService.method1();

Upvotes: 3

Related Questions