Files and folders

The recommended folder structure of the application is to separate features from components. This enforces the idea that a feature is not tied to the UI, they can be implemented in isolation and used across UI components, no matter what page they are on.

pages/
  index.tsx
  /PageA
    index.tsx
    ComponentA.tsx
    ComponentB.tsx
  
features/
  FeatureA/
    index.ts
    Feature.tsx
    Feature.test.tsx
    
environment/
  index.tsx
  EffectA/
    test.ts
    browser.ts
    index.ts

Pages

pages/
  index.tsx
  /Project
    index.tsx
    Project.tsx
    SideBar.tsx

Applications typically has navigation to different pages, where a page reflects a feature. The index.tsx of the pages folder would hold the router.

pages/index.tsx
import React from "react";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { DashboardPage } from './dashboard'
import { ProjectPage } from './project'

export const Pages = () => (
  <Router>
    <Switch>
      <Route exact path="/">
        <DashboardPage />
      </Route>
      <Route path="/projects/:id">
        <ProjectPage />
      </Route>
    </Switch>
  </Router>
);

Each page has its own index.tsx file mapping any router params to the feature. This is an important separation to not make features dependent on a router.

Any children components of the feature now has access to the feature itself. You might compose a layout with multiple features in this file.

pages/project/index.tsx
import { ProjectFeature } from '../features/Project'
import { Project } from './Project'

export const ProjectPage = () => {
  const { id } = useParams<{ id: string; }>();

  return (
    <ProjectFeature id={id}>
      <Project />
    </ProjectFeature>
  )
}

Features

features/
  FeatureA/
    index.ts
    Feature.tsx
    Feature.test.tsx

The application logic is expressed as provider components. Read more in features on how to define a feature. Any related utilities and tests is defined within the same folder.

Environment

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

This folder contains all the environment effects the application needs to operate. Each environment effect has its own folder where it defines how to operate in the different environments, typically test and browser.

The main index.tsx file contains the provider for exposing the environment to the features.

import { createEnvironment } from 'react-states'
import { EffectA } from './EffectA'

export interface Environment {
  effectA: EffectA
}

const {
  EnvironmentProvider,
  useEnvironment
} = createEnvironment<Environment>()

export {
  EnvironmentProvider,
  useEnvironment
}

Providing the actual environment happens in the main file of the application. For example:

import { Environment, EnvironmentProvider } from '../environment'
import { createEffectA } from '../environment/effectA/browser'

const environment: Environment = {
  effectA: createEffectA()
}

const App = () => {
  return (
    <EnvironmentProvider environment={environment}>
      {/* The app components */}
    </EnvironmentProvider>
  )
}

Last updated

Was this helpful?