Application Life Cycle Hooks

Because feature-u is in control of launching the app, life cycle hooks for the application can be introduced, allowing features to perform app-specific initialization, and even inject components into the root of the app.

Two hooks are provided through the following built-in Feature aspects:

  1. Feature.appWillStart - invoked one time at app startup time
  2. Feature.appDidStart - invoked one time immediately after app has started

Application Life Cycle Hooks greatly simplify your app's mainline startup process, because initialization specific to a given feature can be encapsulated in that feature.

appWillStart

The Feature appWillStart() life-cycle hook is invoked one time, just before the app starts up.

API: appWillStart({fassets, curRootAppElm}): rootAppElm | falsy

This life-cycle hook can do any type of initialization. For example: initialize your database:

appWillStart({fassets, curRootAppElm}) {
  initFireBase();
}

Injecting DOM Content

In addition, the appWillStart() life-cycle hook can optionally supplement the app's top-level root element (i.e. react component instance). Any significant return (truthy) is interpreted as the app's new rootAppElm.

Here is an example that injects new root-level content:

appWillStart({fassets, curRootAppElm}) {
  ... any other initialization ...
  return (
    <Drawer ...>
      {curRootAppElm}
    </Drawer>
  );
}

Here is an example of injecting a new sibling to curRootAppElm:

appWillStart: ({fassets, curRootAppElm}) => [React.Children.toArray(curRootAppElm), <Notify key="Notify"/>]

IMPORTANT:

When injecting DOM content (via the function return), the supplied curRootAppElm parameter must be included as part of this definition. The curRootAppElm parameter (when non-null) represents content from other features (within your app) or aspects (used by your app). As a result, by including it in your injection, it accommodates the accumulative process of other feature/aspect injections!

This is outside the control of feature-u, and if you neglect to do it, you will be silently dropping content on the floor ... wondering why some feature/aspect is NOT working.

This constraint even extends to cases where the content you are injecting doesn't support children. In this case you need to throw an error, and emit applicable context in a log. Here is an example:

appWillStart({fassets, curRootAppElm}) {
  // MyContent does NOT support children
  // ... insure we don't clobber any supplied content
  if (curRootAppElm) {
    const msg = "***ERROR*** <MyContent> does NOT support children " +
                "but another feature/aspect is attempting to inject it's content. " +
                "Please resolve either by adjusting the feature expansion order, " +
                "or promoting <MyContent> through the conflicting artifact.";
    console.log(`${msg} ... conflicting artifact:`, curRootAppElm);
    throw new Error(msg);
  }
  return <MyContent .../>;
}
  • In many cases (such as a feature conflict), this can be resolved by adjusting the feature expansion order.

  • In other cases, it may seem as though you have hit an impasse. For example, if your content doesn't support children, and an aspect you are using doesn't support children. Normally this doesn't mean that you can't use your component, it merely means that you must promote your component in a different way ... most likely through the Aspect in conflict.

Because this check is rather tedious, feature-u provides a convenient assertNoRootAppElm() function that performs this check on your behalf. The following code snippet is equivalent:

appWillStart({fassets, curRootAppElm}) {
  assertNoRootAppElm(curRootAppElm, '<MyContent>'); // insure no content is clobbered (children NOT supported)
  return <MyContent .../>;
}

appDidStart

The Feature appDidStart() life-cycle hook is invoked one time immediately after app has started.

API: appDidStart({fassets, [appState], [dispatch]}): void

Because the app is up-and-running at this time, you have access to the appState and dispatch() function ... assuming you are using redux (when detected by feature-u's plugable aspects).

A typical usage for this hook is to dispatch some type of bootstrap action. Here is a startup feature, that issues a bootstrap action:

appDidStart({fassets, appState, dispatch}) {
  dispatch( actions.bootstrap() );
}

results matching ""

    No results matching ""