Environment interface
Last updated
Was this helpful?
Last updated
Was this helpful?
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.
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.
So let us examine this by example.
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:
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.
Note that returning promises is not encouraged as React can see their resolvements as possible memory leaks. Read more about subscriptions to see how to implement environment effects in the react-states architecture
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:
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:
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:
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:
The same effect can be implemented for the test environment doing:
Best practices
The features never expresses environment variables in their implementation. You rather pass environment variables when creating an effect. For example:
This ensures two things:
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)
You have a single point of understanding how these environment effects are configured, including what environment variables are actually being consumed