tao.js Reactor for React

This is a description for part of the first ("original") API for integrating the TAO with React. For a description of the Current API which provides a more React-like declarative approach, take a look here.

Now that we know how to use Adapters to use our React Components as handlers for Application Contexts in the TAO, we need to learn how to render them in the UI.

@tao.js/react provides the Reactor Component to accomplish this by working with the Adapters we create.

Not much here to see

Reactor components are specifically designed to be simple to use dumb container components that will render whatever is determined by the TAO via the Adapter to which it is attached.

To use a Reactor we will need to import it as well as have access to (or import and create) an Adapter. It's usual to create them together, allowing all of our other Component definitions used by the Adapter to be isolated and defined on their own where they can be regular React Components without any knowledge of either the Adapter or Reactor.

Here's an example of creating and setting up an Adapter and then attaching a Reactor to it:

import React from 'react';
import TAO from '@tao.js/core';
import { Adapter, Reactor } from '@tao.js/react';
// import child components that will be handlers
import List from './List';
import View from './View';
import Form from './Form';

const spaceAdapter = new Adapter(TAO);
spaceAdapter
  .setDefaultCtx({ term: 'Space', orient: 'Portal' })
  .addComponentHandler({ action: 'List' }, List)
  .addComponentHandler({ action: 'View' }, View)
  .addComponentHandler({ action: ['New', 'Edit'] }, Form);

const SpaceContainer = () => (
  <div>
    <Reactor adapter={spaceAdapter} />
  </div>
);

export default SpaceContainer;

adapter is required

The adapter prop on the Reactor component is required and must be of type Adapter.

It's possible to make an interface out of this and allow more flexiblity but we don't see the point right now.

More details

When a Reactor is created, it first registers itself with the adapter defined in it's props to be notified when the Adapter's adapted handlers have been called by the TAO so that the Reactor can trigger React to render itself, specifically its child Component.

The child Component of a Reactor is the component that is currently set for the Adapter. This is why we won't have a single global Adapter like we do for the TAO, rather each Adapter is acting as a publisher for any Reactors that care to subscribe for components.

adapter is a prop

Because adapter is a prop to the Reactor, it is possible to change the adapter on the fly.

Although the Reactor is written to be simple, it's not so dumb as we make it. If you do change the adapter prop, it will check to see if it is different before unregistering from the previous and registering with the new Adapters for updates.

Additionally, when the Reactor is unmounted, it will unregister itself so as not to receive more updates from the Adapter, allowing it to be garbage collected having no references leaking.

children are ignored

The Reactor is designed to render child Components based on what Application Contexts are set on the TAO via the Adapter to which it is attached. Currently, any child Components of a Reactor will be ignored and not rendered as part of the UI.

export function MyContainer() {
  return (
    <div>
      <Reactor adapter={myAdapter}>
        {/* everything below is ignored */}
        <MyOtherComponent theme="myTheme" data={stuff} />
        <MyOtherContainer>
          <ChildLikeDemeanor />
        </MyOtherContainer>
      </Reactor>
    </div>
  )
}

If it makes sense, this could be revisited in the future.

Additional props

Just like the Adapter's additional props, Reactors can be given props beyond the required adapter to make it work.

export function MyContainer() {
  return (
    <div>
      <Reactor adapter={myAdapter} theme="myTheme" user={currentUser} />
    </div>
  )
}

Adapter's additional props are assigned when the Component handler is added, so the props become default for a particular Component when a particular AppCon is set on the TAO.

This differs from Reactor additional props in that whatever is set on the Reactor Component as props will be passed down to the instantiated child Component.

Think of Reactor additional props as global to the possible children of the Reactor.

If there is conflict and a prop is defined for both a Reactor and Adapter's Component handler, the Component handler's prop coming from the Adapter will take precedence and be used to set the value of the prop on the child Component.

Special Note: because these additional props are set on the Reactor and not the Adapter and that Reactors attach themselves to their adapters, the Adapter has no knowledge and never sees the additional props coming from a Reactor.

results matching ""

    No results matching ""