# Environment interface

Building a React application with the **react-states** architecture requires you to think about your application as being mounted into an environment. The contract between your application and the environment is the **Environment interface**. This is a contract of specific application requirements. It is up to the environment to meet these requirements. In short, **the application has absolutely no idea what environment it is running in**.

![](/files/-MZ2yZ7ptNHNrEUaYJs5)

The mindset of defining an **Environment interface** is to be very specific. What does the application actually care about? For example the application does not care about **fetch**, **axios** or any other library that fetches data. It does not even care about the urls you use to fetch that data. Actually, it does not even care about where the data is coming from, the application only cares about the data itself.&#x20;

So let us examine this by example.

```typescript
export interface Request {
  get<T>(url: string): Promise<T>
}
```

This is **not** a good interface as you expose to the application that it does an HTTP Get request and the application itself needs to provide the urls for where to fetch the data. A proper **Environment interface** would be:

```typescript
export interface Api {
  getSandbox(id: string): Promise<SandboxDTO>
}
```

With **getSandbox** we are explicit about what the application wants from its environment. But an equally important point is that the application does not need to express any magical strings or typing related to grabbing data, it is already typed and contained where it belongs.

{% hint style="danger" %}
Note that returning promises is not encouraged as React can see their resolvements as possible memory leaks. Read more about [**subscriptions**](/subscriptions.md) to see how to implement environment effects in the **react-states** architecture
{% endhint %}

### Exposing the environment

We expose the environment using a context provider. In the **index.tsx** at the root of the environment folder you can create a simple provider:

```typescript
import React, { createContext, useContext } from "react
import { createEnvironment } from 'react-states'
import { EffectA } from './EffectA'

export interface Environment {
  effectA: EffectA
}

export const EnvironmentContext = createContext<Environment>({} as Environment)

export const useEnvironment = (): Environment => useContext(EnvironmentContext)

export {
  EnvironmentProvider: EnvironmentContext.Provider,
  useEnvironment
}
```

### Implementing an environment effect

```bash
environment/
  index.tsx
  EffectA/
    test.ts
    browser.ts
    index.ts
```

The main file of an environment effects is **EffectA/index.ts**. This file exports the interface for the effect itself and other types related to the effect. It is important that this index file does not hold any implementations, as you do not want to accidentally import something you do not need in a certain environment. It also ensures that all types are imported directly from the effect as:

```typescript
import { TypeA, TypeB } from 'environment/EffectA'
```

The actual implementations resides in a file representing the environment itself. For example **browser.ts** or **test.ts**. But this could be whatever other environments you want to use the features. React is environment agnostic, which means the feature could be **native.ts** or **server.ts**. You could even have a **sandbox.ts** environment where all the environment effects are hardcoded. An example of implementing a browser storage interface would be:

{% code title="environment/Storage/browser.ts" %}

```typescript
import { Storage } from './'

export const createStorage = ():Storage => ({
  set(key, value) {
    localStorage.setItem(key, JSON.stringify(value))
  }
  get(key) {
    return JSON.parse(localStorage.getItem(key) || 'undefined')
  }
})
```

{% endcode %}

You always define environment effects as factories, as this allows to pass in options when instantiating the effect. This could be environment variables and the likes.

The application would consume this effect by:

{% code title="src/main.tsx" %}

```typescript
import * as React from 'react'
import { render } from 'react-dom'
import { createStorage } from '../environment/storage/browser'
import { EnvironmentProvider } from '../environment'

render(
  <EnvironmentProvider value={{
    storage: createStorage()
  }}>
    <App />
  </EnvironmentProvider>
)

```

{% endcode %}

The same effect can be implemented for the test environment doing:

{% code title="environment/Storage/test.ts" %}

```typescript
import { Storage } from './'

export const createStorage = (): Storage => ({
  set: jest.fn(),
  get: jest.fn()
})
```

{% endcode %}

{% hint style="warning" %}
**Best practices**

* [ ] Ensure that the main environment effect file, **index.ts**, only has types exported
* [ ] Implement all environment effects as factories to allow passing options
  {% endhint %}

### Environment variables

The features never expresses environment variables in their implementation. You rather pass environment variables when creating an effect. For example:

{% code title="src/main.tsx" %}

```typescript
import * as React from 'react'
import { render } from 'react-dom'
import { createApi } from '../environment/api/browser'
import { EnvironmentProvider } from '../environment'

render(
  <EnvironmentProvider value={{
    api: createApi(process.env.API_URL)
  }}>
    <App />
  </EnvironmentProvider>
)
```

{% endcode %}

This ensures two things:

1. Environment effects are defined in isolation, they should not make assumptions about the names of environment variables which is out of control of the environment effect. It is up to the application that consumes all the environment effects to pass explicit options to the effects, which could be an environment variable (as seen in the example above)
2. You have a single point of understanding how these environment effects are configured, including what environment variables are actually being consumed

###


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://react-states.csb.dev/environment-interface.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
