83 lines
2.3 KiB
JavaScript
83 lines
2.3 KiB
JavaScript
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
|