import React, { useEffect, useRef } from 'react' import { useLocation, useNavigate } from 'react-router-dom' import PropTypes from 'prop-types' const ActionHandler = ({ children, actions = {}, actionParam = 'action', clearAfterExecute = true, onAction, loading = true }) => { const location = useLocation() const navigate = useNavigate() const action = new URLSearchParams(location.search).get(actionParam) // Ref to track last executed action const lastExecutedAction = useRef(null) // Method to add action as URL param const callAction = (actionName) => { const searchParams = new URLSearchParams(location.search) searchParams.set(actionParam, actionName) const newSearch = searchParams.toString() const newPath = location.pathname + (newSearch ? `?${newSearch}` : '') navigate(newPath, { replace: true }) } // Execute action and clear from URL useEffect(() => { if ( !loading && action && actions[action] && lastExecutedAction.current !== action ) { // Execute the action const result = actions[action]() // Mark this action as executed lastExecutedAction.current = action // Call optional callback if (onAction) { onAction(action, result) } // Clear action from URL if requested and result is true if (clearAfterExecute && result == true) { const searchParams = new URLSearchParams(location.search) searchParams.delete(actionParam) const newSearch = searchParams.toString() const newPath = location.pathname + (newSearch ? `?${newSearch}` : '') navigate(newPath, { replace: true }) } } else if (!action) { // Reset lastExecutedAction if no action is present lastExecutedAction.current = null } }, [ loading, action, actions, actionParam, clearAfterExecute, onAction, location.pathname, location.search, navigate ]) // Return null as this is a utility component return <>{children({ callAction })} } ActionHandler.propTypes = { children: PropTypes.func, actions: PropTypes.objectOf(PropTypes.func), actionParam: PropTypes.string, clearAfterExecute: PropTypes.bool, onAction: PropTypes.func, loading: PropTypes.bool } export default ActionHandler