Skip to content

Creating a dependency

The weather service example demonstrates how useContext can be used to manage configuration and dependencies in a real-world scenario.

In following example consider you have a external dependency WeatherService to provide temperature forecast in your pipeline:

@provider()
export class WeatherService {
  getForecast(city: string): Promise<{ temperature: number }> {
    return Promise.resolve({ temperature: 10 });
  }
}

When working with useContext, there are several key points to keep in mind. The @provider() decorator is essential for marking your context class as injectable.

Expose custom context

Custom hooks provide a clean and reusable way to encapsulate complex logic and state management. When combined with dependency injection, they become even more powerful.

export function useWeather() {
  const weatherService = useContext(WeatherService);
 
  return {
    getForecast: (city: string) => from(weatherService.getForecast(city))
  };
}

Introduce dedicated hook

function getWeatherForecast(city: string) {
    const { getForecast } = useWeather();
 
    return getForecast(city);
}

When implementing dependencies, it's beneficial to separate different concerns into distinct contexts rather than creating one monolithic context. This approach works particularly well for managing various aspects of your application.

  • You might use separate contexts for external service access, ensuring each service is properly isolated.
  • Configuration management can be handled through dedicated contexts, making it easier to modify settings.
  • Feature flags can be managed independently, facilitating gradual rollouts.
  • API settings can be organized in their own context, allowing for easier configuration changes.
  • Any globally shared state can be managed through appropriate contexts, preventing prop drilling while maintaining clean architecture.

Share and cache results

To optimize performance and reduce unnecessary external calls, you can implement caching for your weather forecast requests. This example demonstrates how to combine the weather service with a caching mechanism:

const ttl = 60 * 1000;
 
function getWeatherForecast(city: string) {
    const { getForecast } = useWeather();
 
    return useCache(() => getForecast(city), ['weather-forecast', city], ttl);
}