Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to override default onFailure function within useShowController #5197

Closed
panfiva opened this issue Aug 27, 2020 · 4 comments · Fixed by #6680
Closed

Ability to override default onFailure function within useShowController #5197

panfiva opened this issue Aug 27, 2020 · 4 comments · Fixed by #6680

Comments

@panfiva
Copy link

panfiva commented Aug 27, 2020

Is your feature request related to a problem? Please describe.
We are building a "Show" view that should be displaying different error components when API calls fail based on error status code: "Not found" (when receive 404) , "Access denied" (when receive 403), or "Request failed" (error with any other status)

Current implementation of useShowController will just display ra.notification.item_doesnt_exist message and redirect back to list.

We would like to be able to provide a custom onFailure function to useShowController to be able to override notifications and redirection, and also to return error object in the controller so we can status code to pick appropriate component to render.

Describe the solution you'd like
I would like to change the current implementation

// current
const useShowController = (props: ShowProps): ShowControllerProps => {
    useCheckMinimumRequiredProps('Show', ['basePath', 'resource'], props);
    const { basePath, id, resource } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const redirect = useRedirect();
    const refresh = useRefresh();
    const version = useVersion();
    const { data: record, loading, loaded } = useGetOne(resource, id, {
        action: CRUD_GET_ONE,
        onFailure: () => {
            notify('ra.notification.item_doesnt_exist', 'warning');
            redirect('list', basePath);
            refresh();
        },
    });

    const resourceName = translate(`resources.${resource}.name`, {
        smart_count: 2,
        _: inflection.humanize(inflection.pluralize(resource)),
    });
    const defaultTitle = translate('ra.page.list', {
        name: resourceName,
    });

   return {
        loading,
        loaded,
        defaultTitle,
        resource,
        basePath,
        record,
        version,
    };

to the following:

// proposed
const useShowController = (props: ShowProps): ShowControllerProps => {
    useCheckMinimumRequiredProps('Show', ['basePath', 'resource'], props);
    const { basePath, id, resource } = props;
    const translate = useTranslate();
    const notify = useNotify();
    const redirect = useRedirect();
    const refresh = useRefresh();
    const version = useVersion();

  // moved
   const resourceName = translate(`resources.${resource}.name`, {
        smart_count: 2,
        _: inflection.humanize(inflection.pluralize(resource)),
    });

    // moved
    const defaultTitle = translate('ra.page.list', {
        name: resourceName,
    });

   // new code
    const onFailureCb =  props.onFailure ||
      ((props) => {
        notify('ra.notification.item_doesnt_exist', 'warning')
        redirect('list', props.basePath)
        refresh()
      });

   // added "error" in return
    const { data: record, loading, loaded, error } = useGetOne(resource, id, {
        action: CRUD_GET_ONE,
        onFailure: () => {
            // changed
            onFailureCb({ basePath, id, resource, error, notify, redirect, refresh, resourceName, defaultTitle})
        },
    });
   return {
        loading,
        loaded,
        defaultTitle,
        resource,
        basePath,
        record,
        version,
        // added "error" in return        
        error
    };
  • If onFailure is not provided, the only change functional change will be error added to the return. This object will allow me to query error.status and render different error-handling components.
  • onFailure will give me the ability to override current onFailure behavior, to use different or ignore notification, redirect and refresh calls. Note that onFailureCb({ id, resource, error, resourceName, defaultTitle}) parameters are not needed for the use case above; however they may be useful when issuing custom notifications to users and are also needed for logging errors into our web log management system.

Describe alternatives you've considered
I have copied current useShowController and customized it as discussed above.

Additional context
n/a

@Dude29
Copy link

Dude29 commented Jun 14, 2021

Any updates on this issue?

@djhi
Copy link
Collaborator

djhi commented Jun 14, 2021

We'll gladly accept a PR to implement it, targeting the next branch :)

@Dude29
Copy link

Dude29 commented Jun 15, 2021

Unfortunately I don't really have the time to submit a PR on this issue and test it thoroughly enough 😞

In any case, is there any alternative way to manipulate or override the default behavior of the failure scenario for Show components? Perhaps intervining directly in the redux store if such a thing is possible?

In my use case it is not really pratical to rewrite a detail component using <Show> component to use dataProvider.useGetOne(). Even rewriting it to use a <ShowController> component wouldn't help much as this component doesn't allow overriding the default onFailure callback.

@fzaninotto
Copy link
Member

This issue hasn't received much interest from the community. As the core team doesn't need this feature and won't spend time implementing it, I'm closing it.

Writing your own show controller logic is the right way to go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants