Plugin Templates

Copy-pastable example snippets for accelerating plugin development

Method of a component

In this example - render

const render = (args, callback, instance) => (
   <>
       { callback.apply(instance, args) }
   </>
);

export default {
   'Component/NAME/Component': {
       'member-function': {
           render
       }
   }
};

Container functions

Common case - when you need to pass an additional function from parent to child

export class NAMEContainerPlugin {
   containerFunctions = (originalMember, instance) => ({
       ...originalMember,
       handleSomething: this.handleSomething.bind(instance)
   });

   handleSomething(arg) {
       console.log(arg);
   }
}

const { containerFunctions } = new NAMEContainerPlugin();

export default {
   'Component/NAME/Container': {
       'member-property': {
           containerFunctions
       }
   }
};

Prop types

You need to add an additional prop to propTypes after passing an additional prop to the component? No problem!

import PropTypes from 'prop-types';

const propTypes = (originalMember) => ({
   ...originalMember,
   handleSomething: PropTypes.func.isRequired
});

export default {
   'Component/NAME/Component': {
       'static-member': {
           propTypes
       }
   }
};

Default props

Not required new propType - do this.

const defaultProps = (originalMember) => ({
   ...originalMember,
   pluginProp: 'PluginProp'
});

export default {
   'Component/NAME/Container': {
       'static-member': {
           defaultProps
       }
   }
};

More state

Additional fields for the state.

const state = (originalMember) => ({
   ...originalMember,
   PluginState: 'PluginState'
});

export default {
   'Component/NAME/Container': {
       'member-property': {
           state
       }
   }
};

Adding a Reducer to the Redux Store

Add reducers to the application as follows.

import { NAMEReducer } from '../store/NAME;

const getStaticReducers = (args, callback, instance) => ({
   ...callback(...args),
   NAMEReducer
});

export const config = {
   'Store/Index/getReducers': {
       function: getStaticReducers
   }
};

export default config;

Query fields

Additional query field shown below!

const _getMETHODFields = (args, callback, instance) => [
   ...callback.apply(instance, args),
   'field_name'
];

export default {
   'Query/NAME': {
       'member-function': {
           _getMETHODFields
       }
   }
};

Reducer Initial State

const getInitialState = (args, callback, instance) => (
    {
        ...callback(...args),
        new_state: 'true'
    }
);

export default {
    'Store/NAME/Reducer/getInitialState': {
        function: getInitialState
    }
};

mapStateToProps

Connect an additional piece of state to the component

const mapStateToProps = (args, callback, instance) => {
   const [state] = args; 

   return {
       ...callback(...args),
       pluginProp: state.SomeReducer.someState
   };
};

export default {
   'Component/NAME/Container/mapStateToProps': {
       function: mapStateToProps
   }
};

mapDispatchToProps

Connect an additional dispatch function to the component

const { letsDoSomething } = import('Store/STORENAME/STORENAME.action');

const mapDispatchToProps = (args, callback, instance) => {
   const [dispatch] = args;

   return {
       ...callback(...args),
       doSomething: (value) => dispatch(letsDoSomething(value))
   };
};

export default {
   'Component/NAME/Container/mapDispatchToProps': {
       function: mapDispatchToProps
   }
};

Adding a Route to the Router

Note how we use async import(...) statement here in order to optimize bundle sizes!

import { lazy } from 'react';
import { Route } from 'react-router-dom';

import { withStoreRegex } from 'Component/Router/Router.component';

export const YourPage = lazy(() => import(
    /* webpackMode: "lazy", webpackChunkName: "extension-name" */ 
    '../route/YourPage'
));

const SWITCH_ITEMS_TYPE = (originalMember) => [
   ...originalMember,
   {
       component: (
           <Route
             path={ withStoreRegex('/path') }
             render={ (props) => <YourPage { ...props } /> }
           />
       ),
       position: 100
   }
];

export const config = {
   'Component/Router/Component': {
       'member-property': {
           SWITCH_ITEMS_TYPE
       }
   }
};

export default config;

Extending maps

Example: creating a new tab in MyAccount

import { lazy } from 'react';

import { 
    MY_TAB_PATH,
    MY_TAB_NAME
} from '../component/MyAccountCustomTab/MyAccountCustomTab.config';

import MyAccountCustomTab from '../component/MyAccountCustomTab';

const renderMap = (originalMember) => ({
   [MY_TAB_NAME]: MyAccountCustomTab,
   ...originalMember,
});

const tabMap = (originalMember) => ({
   ...originalMember,
   [MY_TAB_NAME]: {
       url: `/${ MY_TAB_PATH }`,
       name: __('My Tab')
   }
});

export default {
   'Route/MyAccount/Container': {
       'static-member': {
           tabMap
       }
   },
   'Route/MyAccount/Component': {
       'member-property': {
           renderMap
       }
   }
};

Last updated