# Basic Domain Model

### TLDR;

```bash
npx reactium component # and follow the prompts
```

## Basic Artifacts

### route.js

Reactium aggregates all **route.js** or **reactium-route\*.js** files into a list of routes used to render similar to [React Router Route](https://reacttraining.com/react-router/web/api/Route) components. Reactium also extends this concept to allow controlled transitionary states between routed components using `Reactium.Routing`

{% hint style="info" %}
A route can have most properties that are supported by [\<Route />](https://reacttraining.com/react-router/web/api/Route) component of React Router (e.g. path, exact, component)\
\
Additional Special Properties: transitions, transitionStates (See [Animating Reactium Routes](https://docs.reactium.io/reactium/reactium-guides/animating-react-routes))
{% endhint %}

{% code title="/MyComponent/reactium-route-mycomponent.js.js" %}

```javascript
import { MyComponent } from './MyComponent';

export default {
    id: 'MyComponent-route-string-unique',
    path: ['/test'],
    exact: true,
    component: MyComponent,
    order: 0,

    // optional route transition controls
    transitions: false, // defaults to false
    transitionStates: [
        {
            active: 'previous',
            state: 'EXITING',
        },
        {
            active: 'current',
            state: 'LOADING',
        },
        {
            active: 'current',
            state: 'ENTERING',
        },
        {
            active: 'current',
            state: 'READY',
        },
    ];
};
```

{% endcode %}

{% hint style="warning" %}
If you set transition to **`true`** in your `route.js`, you will need to manage the current routing state in your code programmatically, advancing to the next state using `Reactium.Routing.nextState()`. See [Animating React Routes](https://docs.reactium.io/reactium/reactium-guides/animating-react-routes) for more information.
{% endhint %}

{% hint style="info" %}
Unlike `<Route>` from React Router, which is defined declaratively in your static application, the order of these routes is determined by sorting on the **order** property.
{% endhint %}

{% hint style="success" %}
All the properties in this object that you specific that are not pertaining to matching the route will be passed on as properties to your component. This is useful when multiple routes render the same component with a different context (in addition to route params and search query).
{% endhint %}

### \<Component>.jsx

When generated by **`reactium`** cli, the boilerplate for this file will vary based on the type of component you specified when generating.&#x20;

> See: [Creating A Component](https://docs.reactium.io/reactium/domain/broken-reference) for additional information

{% hint style="warning" %}
**YourComponent.jsx** is conceptually part of your domain, but it is not added to the built-time manifest `src/manifest.js`. Your component must be registered to be used in the application:

* **reactium-route-\<yourcomponent>.js** - import component here to assign it to a route
* **reactium-hooks.js** - import here to register component globally for shared use (using `Reactium.Component.register()`), or to a rendering zone (using `Reactium.Zone.addComponent()` )
  {% endhint %}

{% hint style="info" %}
Use **`npx reactium component`** to create these files.
{% endhint %}

### \_reactium-style.scss

One opinion of Reactium is to **NOT** use css-in-js by loading and processing styles using Webpack. Instead we use gulp and dart SASS to compile one or more CSS stylesheets. This would ordinarily make placing your styles with your component challenging, as you would have a lot of extra work to manage the imports into your main stylesheet.

This is no sweat with Reactium. By placing a **scss** partial with a filename *beginning with* **`_reactium-style`** in your domain folder, Reactium will automatically manage the imports into a common generated partial, **`src/assets/style/_scss/_reactium-modules.scss`**

This generated partial is included in the compilation of the style.css for your application by default with a new Reactium install.

There are some common directories or filename suffixes that will result in your partial being sorted differently in the generated **\_reactium-modules.scss** partial:

| Directory                           |                Suffix               | Priority |
| ----------------------------------- | :---------------------------------: | :------: |
| **mixins**/\_reactium-style.scss    |   \_reactium-style-**mixins**.scss  |   -1000  |
| **variables**/\_reactium-style.scss | \_reactium-style-**variables**.scss |   -900   |
| **base**/\_reactium-style.scss      |    \_reactium-style-**base**.scss   |   -800   |
| **atoms**/\_reactium-style.scss     |   \_reactium-style-**atoms**.scss   |     0    |
| **molecules**/\_reactium-style.scss | \_reactium-style-**molecules**.scss |    800   |
| **organisms**/\_reactium-style.scss | \_reactium-style-**organisms**.scss |    900   |
| **overrides**/\_reactium-style.scss | \_reactium-style-**overrides**.scss |   1000   |

{% hint style="info" %}
The default priority of **\_reactium-style.scss** is the same as organism (800), and is the default generated filename when you create a module using **`arcli component`**

You can also use the optional generated **reactium-gulp.js** file that comes with your style to define a different priority of your style partial by regex pattern.
{% endhint %}

{% hint style="success" %}
We highly recommend the book [*Atomic Design*](https://atomicdesign.bradfrost.com/) by [Brad Frost](http://bradfrost.com/) to understand the significance of these distinctions!
{% endhint %}

### reactium-hooks.js

If you're looking to get some things done before the first render or in the file scope, this is the place. Many of the Reactium SDK functions are available and those that are not, can be accessed after a plugin has been successfully registered.&#x20;

{% tabs %}
{% tab title="reactium-hooks.js" %}
{% code title="MyComponent/reactium-hooks.js" %}

```jsx
import Component from './index';
import Reactium from 'reactium-core/sdk';

Reactium.Plugin.register('MyComponent-plugin').then(() => {
    // register 'MyComponent' to be used in other components
    // using the useHookComponent React hook
    Reactium.Component.register('MyComponent', Component);
});

Reactium.Hook.register('some-custom-hook', async (param1, param2, context) => {
  // do something in this hook
  // often mutate a shared context object (always the last parameter)
});

Reactium.Hook.register('routes-init', async () => {
    // alternative to statically defined route.js
    // some hypothetical custom cloud function 'my-route'
    const { routes = [] } = await Reactium.Cloud.run('my-routes', { where: 'MyComponent'});

    // register all the routes where this component should render dynamically
    for (const route of routes) {
      Reactium.Routing.register({
       ...route,
       component: Component,
      });
    }
});
```

{% endcode %}
{% endtab %}

{% tab title="SomeComponent.js" %}

```javascript
import React from 'react';
import { useHookComponent } from 'reactium-core/sdk';

const SomeComponent = props => {
  // share a component from another place
  const MyComponent = useHookComponent('MyComponent');
  return <MyComponent />
};
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**reactium-hooks.js** provides a generic file scope for your domain to create a build-time plugin for your application. Registering Hook callbacks, registry objects, registered components, declaring components to render in generic application rendering zones, and more. The example above is one of infinite ways you can extend your application with this artifact.
{% endhint %}

### domain.js

There are times when you will need to describe the domain for certain situations. The `domain.js` file is where that should happen. An important feature of `domain.js` is it will allow you to prevent namespace conflicts between your domains when Reactium builds your build-time manifest.

{% hint style="info" %}
For instance: when creating a component library that will be imported as an NPM module into another Reactium project.&#x20;
{% endhint %}

{% code title="/MyComponent/domain.js" %}

```jsx
module.exports = {
    name: 'MyComponent',
};
```

{% endcode %}

{% hint style="info" %}
**domain.js** is used by build-time manifest tools to determine what domain name will be used to group dynamically loaded domain artifacts.
{% endhint %}

### services.js

Reactium aggregates all **services.js** or **reactium-service\*.js** files into the **services** property of the dependencies module default export.&#x20;

A typical **services.js** file may look like this:

{% tabs %}
{% tab title="Services" %}
{% code title="/MyComponent/services.js" %}

```jsx
import axios from 'axios';
import { restHeaders } from 'dependencies';

const restAPI = 'http://demo3914762.mockable.io';

const fetchHello = () => {
    const hdr = restHeaders();
    return axios.get(restAPI + '/hello', { headers: hdr }).then(({ data }) => data);
};

const fetchGoodBye = () => {
    const hdr = restHeaders();
    return axios.get(restAPI + '/goodbye', { headers: hdr }).then(({ data }) => data);
};

export default {
    fetchHello,
    fetchGoodBye,
};
```

{% endcode %}
{% endtab %}

{% tab title="Usage" %}
{% code title="/MyComponent/actions.js" %}

```jsx
import deps from 'dependencies';

export default {
    mount: params => dispatch => {
        deps().services.MyComponent.fetchHello().then(data => {
            dispatch({ type: deps().actionTypes.TEST_MOUNT, payload: data });
        });
    },
};
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="danger" %}
Services are an area where it may seem like a good idea to share between domains. This is generally not encouraged as domains should be as self sufficient as possible. If you find the need to share a service, consider making it a domain above or adjacent to the consumer domains. *You may also want to consider* [*extending the Reactium SDK*](https://docs.reactium.io/reactium/domain/broken-reference)
{% endhint %}

### reactium-boot.js

You can think of **reactium-boot.js** to be for the Reactium Node/Express server, what **reactium-hook.js** is for the client application. Generally, this file is used for hooks that are meant to be used server-side, such as registering Express middleware, server globals, loading scripts and stylesheets, and manipulating the server template.

See the [Server Hooks in the Reactium API Reference](https://atomic-reactor.github.io/Reactium/#api-Hooks).

{% code title="reactium-boot.js" %}

```javascript
import Reactium from 'reactium-core/sdk';
Reactium.Hook.register('Server.AppScripts', async (req, AppScripts) => {
    AppScripts.register('my-onsite-script', {
        path: '/assets/js/some-additional.js'
        footer: true, // load in footer (optional)
        header: false, // don't load in header (optional)
        order: 1, // scripts will be ordered by this
    });
});
```

{% endcode %}

### test.js

Reactium adds a test for your domain when it the test command is run.&#x20;

A typical **test.js** file may look like this:

{% code title="/MyComponent/test.js" %}

```jsx
import React from 'react';
import MyComponent from './index';
import { shallow } from 'reactium-core/enzyme';

test('<MyComponent />', () => {
    const component = shallow(<MyComponent />);

    expect(component.html().length).toBeGreaterThan(0);
});
```

{% endcode %}

{% hint style="danger" %}
If Redux is being used in the above component **MyComponent** would be imported from **./MyComponent** instead of **./index**
{% endhint %}
