javascriptreactjsrelayjs

React Relay project directory structure organization


I'm starting to build projects using Relay and I[m a little confused about my project structure (I do use isomorphic approach).

Here is my normal React project structure:

-- project
     |-----src
     |       |---components (React components with their respective .css styles)
     |       |---containers (React/Redux containers)
     |       |---helpers (Helpers, common to components and containers)
     |       |---redux (Redux stores)
     |       server.js (node server code)
     |       client.js (client code)
     |       routes.js (routes)
     |       config.js (application config)
     |
     |-----static
     |       |-- ... (static files)
     |-----webpack 
     |       |-- ... (webpack configuration files)

In React/Redux, the container is conceptually a "smart component" (see this link and makes sense to differentiate them in component (a pure React component) and container (the "smart component" with redux data)

Now as I'm moving to Relay, the container is conceptually related to data only, with relation to the React component (see here), and that would change a little bit the directory structure above.

Questions:

a) Shall I keep the components and containers as separate directory ?

b) Shall I call them all components and structure the itens as:

  src
   |------ containers
               |-------- itemcontainer.js (relay container)
               |-------- itemcomponent.js (react component)
               |-------- itemcomponent.css (react component styling)

In that case, how to deal with components that has no data associated ?

c) Shall I do something different ?

What would be the best approach to organize components, containers and styling itens in a React/Relay architecture ?

What would be the best approach to organize a React/Relay project structure ?


Solution

  • Your questions are really a matter of preference, but if you are trying to maximize developer experience:

    Best not to separate your "containers" and "components", as to make it easy to change the data requirements of the component. Regardless if you're using your terminal or a GUI (like File Explorer, Finder, or VSCode) to navigate your project, having everything about the component in one directory makes it easy to make changes, especially in the long run and in large teams, where you want to limit friction. Just having to think about traversing the file structure, might deter "lazy" developers from fixing bugs or doing simple tasks.

    I would suggest this structure, but take it with a grain of salt:

    src
       |------ components
             |-------- ComponentName
                   |-------- index.js          (relay container)
                   |-------- ComponentNameUI.js  (react component)
                   |-------- ComponentName.css (react component styling)
       |------ ui
             |-------- ComponentName
                   |-------- index.js          (react component)
                   |-------- ComponentName.css (react component styling)
    

    Where all your "smart" Relay components ("container" + "presentation", which you call "component") would be in the components/ directory, and your "dumb" components that don't have anything to do with Relay, such as components of your Design System (like Button, Avatar and such), would be in the ui/ directory (you can name it however you'd like).

    If you want an easy way to emplace and enforce the above structure, I created a CLI, relay-butler, that takes in GraphQL fragments and outputs Relay components in that structure. It's TypeScript by default, but you can customize the templates however you'd like and change it to JavaScript.

    I also suggest reading the page about Thinking in Relay in the relay.dev docs, which doesn't tell you how to structure your project but does give you an idea of how you might want to go about it.

    But most importantly, as Dan Abramov, one of co-authors of create-react-app, once said: "move files around until it feels right" (https://twitter.com/dan_abramov/status/1042364018848145408).