Source: Dispatcher.js

/**
 * This module expose Dispatcher component.
 * @module react-cmf/lib/Dispatcher
 * @see module:react-cmf/lib/action
 */
import PropTypes from 'prop-types';

import { useContext, Children, cloneElement } from 'react';
import cmfConnect from './cmfConnect';
import action from './action';
import actionCreator from './actionCreator';
import { RegistryContext } from './RegistryProvider';

/**
 * This component purpose is to decorate any component and map an user event
 * to an action to be dispatched
 * @example
function myfunc(event, props, context) {
}
<Dispatcher onClick={myfunc}>
	<ChildrenElement />
</Dispatcher>
 */
export function Dispatcher(props) {
	const registry = useContext(RegistryContext);
	// console.log('@@@ registry', registry);

	/**
	 * on any even just try to find a onTHEEVENT props.
	 * If found execute it with the common stuff
	 * (event, props, context)
	 * @param  {object} event     the react event dispatched event
	 * @param  {string} eventName the name of the event
	 */
	function onEvent(event, eventName) {
		if (props.stopPropagation) {
			event.stopPropagation();
		}
		if (props.preventDefault) {
			event.preventDefault();
		}
		if (props[eventName]) {
			props.dispatchActionCreator(props[eventName], event, props);
		}
	}

	function checkIfActionInfoExist() {
		action.getOnProps(props).forEach(name => {
			if (typeof props[name] === 'string') {
				actionCreator.get({ registry }, props[name]);
			}
		});
	}

	checkIfActionInfoExist();
	const onProps = action.getOnProps(props);
	const childrenWithProps = Children.map(props.children, child => {
		const newProps = {};
		onProps.forEach(name => {
			newProps[name] = event => onEvent(event, name);
		});
		return cloneElement(child, newProps);
	});
	return Children.only(childrenWithProps[0]);
}

Dispatcher.propTypes = {
	children: PropTypes.node.isRequired,
	stopPropagation: PropTypes.bool,
	preventDefault: PropTypes.bool,
	dispatchActionCreator: PropTypes.func,
};
Dispatcher.displayName = 'Dispatcher';
Dispatcher.defaultProps = {
	stopPropagation: false,
	preventDefault: false,
};
const ConnectedDispatcher = cmfConnect({
	withDispatchActionCreator: true,
})(Dispatcher);

/**
 * This component purpose is to decorate any component and map an user event
 * to an action to be dispatched
 * @example
<Dispatcher onClick="actionCreator:identifier" onDrag="actionCreator:anotherid">
	<ChildrenElement />
</Dispatcher>
 */
export default ConnectedDispatcher;