# Plugin Templates

## Method of a component

In this example - `render`

```javascript
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

```javascript
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!&#x20;

```javascript
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.

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

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

## More state

Additional fields for the state.

```javascript
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.&#x20;

```javascript
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!

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

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

## Reducer Initial State

```javascript
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

```javascript
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

```javascript
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!

```javascript
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

```javascript
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
       }
   }
};
```
