openapi-dotnet-react-typescript-fetch-example

An example project showing how to use the OpenAPI typescript-fetch HTTP client with React

Stars
5

openapi-dotnet-react-typescript-fetch-example

An example project that demonstrates how to:

Project Overview

 HTTPClient/lib  # The generated typescript-fetch HTTP client
 ReactApp        # A TypeScript React front-end application that consumes the HTTP Client
 WebAPI          # A .NET 5 web API that provides the OpenAPI definitions

Generating the HTTP Client

The following software is required:

Run the folllowing to generate the client:

dotnet tool restore
dotnet msbuild -target:GenerateHTTPClient WebAPI -property:Configuration=Release

The build script does the following:

  • Builds the WebAPI .NET application
  • Extracts the OpenAPI spec from the .NET application to location ./HTTPClient/api-spec.json
  • Runs some npm scripts within ./HTTPClient to generate the client (Refer to the scripts in ./HTTPClient/package.json)

Consuming the HTTP Client with React

API Setup

API instances and react-query are setup within ./ReactApp/src/api, for example:

import {
  Configuration,
  ConfigurationParameters,
  WeatherForecastApi,
} from 'example-service-client';
import { ApiMiddleware } from './ApiMiddleware';

const configParams: ConfigurationParameters = {
  basePath: 'https://localhost:5001',
  middleware: [new ApiMiddleware()],
};

const apiConfig = new Configuration(configParams);

export const apiClient = {
  weatherForecastApi: new WeatherForecastApi(apiConfig),
};

export type ApiClient = typeof apiClient;

Query Hooks

Query hooks call the generated HTTP Client methods, and support request cancellation, for example:

import { WeatherForecast } from 'example-service-client';
import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query';
import { ResponseError } from '../types';
import { withQueryCancellation } from '../util/withQueryCancellation';
import { useApiClient } from './useApiClient';

export const getWeatherForecastKey = 'getWeatherForecast';

export function useGetWeatherForecast(
  options?: UseQueryOptions<Array<WeatherForecast>, ResponseError>
): UseQueryResult<Array<WeatherForecast>, ResponseError> {
  const { weatherForecastApi } = useApiClient();
  return useQuery(
    getWeatherForecastKey,
    withQueryCancellation((signal) =>
      weatherForecastApi.weatherForecastGet({ signal })
    ),
    options
  );
}

Query hooks are called in React components, for example:

export const App: React.FC = () => {
  const queryClient = useQueryClient();

  const {
    data = [],
    error,
    isFetching,
    refetch,
  } = useGetWeatherForecast({
    enabled: false,
  });

  const getWeatherForecast = () => {
    if (!isFetching) {
      refetch();
    }
  };

  const cancelGetWeatherForecast = () => {
    void queryClient.cancelQueries(getWeatherForecastKey);
  };

  return (
    <div className="App">
      <button className="App-link" onClick={getWeatherForecast}>
        Get Weather Forecast
      </button>
      {isFetching && (
        <p>
          Loading...(
          <button className="App-link" onClick={cancelGetWeatherForecast}>
            Cancel
          </button>)
        </p>
      )}
      {error && <p>Error! {getResponseErrorMessage(error)}</p>}
      {data.map((forecast, i) => (
        <p key={i}>
          {forecast.summary} ({forecast.temperatureC}C)
        </p>
      ))}
    </div>
  );
};

Running the WebAPI

dotnet run --project WebAPI

Swagger is then available at: https://localhost:5001/swagger/index.html

Running the React App

npm start --prefix ReactApp

How this project was bootstrapped

dotnet new gitignore
dotnet new tool-manifest
dotnet new nugetconfig
dotnet tool install Swashbuckle.AspNetCore.Cli
dotnet new sln --name OpenAPITypeScriptFetchExample
dotnet new webapi -o WebAPI
dotnet sln add WebAPI

# .editorconfig config manually created from https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options

npx create-react-app react-app --template typescript
mv react-app ReactApp

TODO

  • Add bearer token auth to .NET project