Skip to content

Instantly share code, notes, and snippets.

@suzubara
Created February 12, 2020 21:10
Show Gist options
  • Save suzubara/91156f6af8cffcd768049d9c933821b3 to your computer and use it in GitHub Desktop.
Save suzubara/91156f6af8cffcd768049d9c933821b3 to your computer and use it in GitHub Desktop.
Front End project structure

Frontend Architecture

Directory Structure

All of the frontend (browser) code is located in /src. Here is a brief outline of the directories & how the code is organized:

  • /src/components - Low-level React Components that are more about rendering UI than handling application logic, and should typically not be connected to providers directly. Aim for abstract, generic components that can be shared across the application easily, and will usually have corresponding stories files for viewing in Storybook.

  • /src/config - High-level configuration definitions relevant to the whole application (such as routes).

  • /src/constants - Define constants here instead of using string literals for any values with specific meaning in the context of the application. For example, data that comes back from the API that may be used in UI logic (such as a user role or casefile status).

  • /src/containers - React Components that are primarily concerned with connecting UI to containers or providers (such as Redux), and sharing behavior or patterns via hooks or higher-order components.

  • /src/content - Content that ends up displayed in the UI to the end-user. This is often expressed as plain text, but can also include JSX nodes in order to support formatted text. An example is defining how specific values from API data should be displayed as user-friendly language.

  • /src/graphql - GraphQL code is in here! (but not all of it!)

    • /src/graphql/fragments - Common GraphQL fragments that may be shared across queries/mutations.

    • /src/graphql/mocks - Not to be confused with testing mocks. This defines client-only schema and resolvers for GraphQL requests that have not yet been implemented in the API.

  • /src/helpers - Miscellaneous utilities that implement logic, data handling, and other common functions used throughout the application. These should not include React-specific code such as JSX, and they should generally be purely functional and well-tested.

  • /src/layout - React components used to render common layout elements, such as header, footer, page content, etc. Similar to the components located in /src/components, they should focus on rendering UI rather than application logic or connecting to providers. However, they are designed such that there should only ever be one instance on each page.

  • /src/pages - React components that correspond to actual routes (URLs). These are responsible for assembling the UI components for a page, and hooking them up with the necessary providers such as Redux or GraphQL. Queries should be co-located with page components, since pages are explicitly dependent on them.

  • /src/store - Redux code is in here! For more info on how we are using Redux alongside GraphQL, read here.

    • /src/store/store.ts - Configures and exports the Redux store
    • Directories in here correspond to reducers, or "slices" of the store. Each directory contains its own types, actions, and reducer. These should all be well-tested.
  • /src/stories - Storybook stories that aren't specific to a single component live here.

  • /src/styles - Sometimes we also have to write CSS.

  • /src/types - Type definitions that are shared throughout the application.

Application Bootstrap

(or, how does all of this come together?)

The primary entry point is src/index.tsx. This file is responsible for:

  • Initializing ApolloClient with our configuration and any client-side mocks.
  • Including the CSS entry point (src/index.scss) so it doesn't feel left out, and so our webpages look pretty.
  • Wrapping the main <App /> component inside of the <ApolloProvider> (GraphQL), the <Provider> (Redux), and the <PersistGate> (redux-persist).
  • Finally, rendering the resulting <App /> component into the DOM (!!)

The next most important file is src/App.tsx. This is the top-level component that is rendered into the DOM. It is responsible for 2 important things:

  • Imposing a global <Layout /> onto all pages.
  • Mapping whatever the current route is to the matching page component. If there is no matching page component, it will render the NotFound page component instead.

To Redux or GraphQL?

A lot of confusion can stem from where to store data and how to access it in React applications. Here's a quick guide:

  • GraphQL is for data you are getting from the API. SABER frontend communicates with the GraphQL server using ApolloClient. ApolloClient is very smart at caching, so when we get API data we don't need to store it anywhere else! Storing API data in Redux would be redundant.
  • Redux is for local application state. That means if there's any UI state that the entire application needs to be aware of, but that doesn't need to be saved to a database for later, we should put it in Redux!
    • Examples include the current page URL, and whether or not a full page modal is open. Also, Redux can be useful for storing mock data that will eventually come from the API, but hasn't been implemented yet.

ReactUSWDS

ReactUSWDS is an internal Truss project aiming to create React implementations of USWDS 2.0 UI components. SABER is the first guinea pig to use ReactUSWDS! If you are building a new UI component that is based on a USWDS design, and might be useful to abstract so it can be shared by other, non-SABER projects, you may want to consider building it in ReactUSWDS instead. You can find more information about contributing to and using ReactUSWDS here.

CSS

If you need to style a specific React component, it is probably best to write a CSS module for that component. CSS modules are co-located with components using the filename convention:

MyComponent.tsx
MyComponent.styles.scss

If you want to use USWDS SCSS utilities in your component, you must include this at the top of the module file:

@import 'path/to/uswdsImports.scss';

Read more information about CSS modules here.

If you really want to edit global styles, all other CSS code is located in src/styles. Make sure to import new files into src/index.scss.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment