Basic Domain Model

Without any plugins, the Reactium framework comes with these fundamental building-block artifacts. Use them to quickly start building DDD functionality.

TLDR;

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 components. Reactium also extends this concept to allow controlled transitionary states between routed components using Reactium.Routing

A route can have most properties that are supported by <Route /> component of React Router (e.g. path, exact, component) Additional Special Properties: transitions, transitionStates (See Animating Reactium Routes)

/MyComponent/reactium-route-mycomponent.js.js
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',
        },
    ];
};

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 for more information.

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.

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).

<Component>.jsx

When generated by reactium cli, the boilerplate for this file will vary based on the type of component you specified when generating.

See: Creating A Component for additional information

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() )

Use npx reactium component to create these files.

_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:

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.

We highly recommend the book Atomic Design by Brad Frost to understand the significance of these distinctions!

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.

MyComponent/reactium-hooks.js
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,
      });
    }
});

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.

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.

For instance: when creating a component library that will be imported as an NPM module into another Reactium project.

/MyComponent/domain.js
module.exports = {
    name: 'MyComponent',
};

domain.js is used by build-time manifest tools to determine what domain name will be used to group dynamically loaded domain artifacts.

services.js

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

A typical services.js file may look like this:

/MyComponent/services.js
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,
};

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

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.

reactium-boot.js
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
    });
});

test.js

Reactium adds a test for your domain when it the test command is run.

A typical test.js file may look like this:

/MyComponent/test.js
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);
});

If Redux is being used in the above component MyComponent would be imported from ./MyComponent instead of ./index

Last updated