question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Provide the default callback to `enhance`

See original GitHub issue

Describe the problem

I’ve seen people try to add a loading state via enhance a couple times. They do something like this:

<form use:enhance={() => {
  loading = true;
  return () => {
    loading = false;
  }
}}>

However, they don’t realize that once you return a callback from the function passed to enhance, the default behavior after a form submission no longer applies and you have to do the following yourself:

  • run invalidateAll if the result was a success
  • run applyAction if the current location matches or the result was a redirect/error

This logic currently happens in the default callback.

This means if you want to extend enhance, e.g. to add a loading state, you have to duplicate that logic, even if your customizations are minimal:

<form use:enhance={() => {
  loading = true;
  return ({action, result}) => {
+    if (result.type === 'success') {
+      await invalidateAll();
+    }
+
+    if (
+      location.origin + location.pathname === action.origin + action.pathname ||
+      result.type === 'redirect' ||
+      result.type === 'error'
+    ) {
+      applyAction(result);
+    }

    loading = false;
  }
}}>

(You could remove the check around applyAction and always apply it, but I don’t like how that diverges you from the default enhance behavior, perhaps without even realizing it).

You can abstract this into a custom action that wraps enhance to reduce the boilerplate, but you won’t get any updates that are made to the default callback behavior, e.g. the changes in https://github.com/sveltejs/kit/pull/6828.

All you wanted to do was toggle a loading state, but now you have to maintain the default enhance behavior as well.

Of course, there are cases where you want to customize the invalidate or applyAction behavior. However, I suspect those cases are more the exception than the norm.

Describe the proposed solution

Provide an additional argument to the callback returned from enhance. Name is bikesheddable, but for the purposes of this issue I’ll call it defaultBehavior. The implementation of this method is the same as fallback_callback. People who want to add some logic after a form submission and preserve the default behavior could call this method instead of recreating the logic themselves. This way, if the default behavior is updated, custom actions calling this method get it for free.

The example above would then look like this:

<form use:enhance={() => {
  loading = true;
  return ({action, result, defaultBehavior}) => {
    defaultBehavior();
    loading = false;
  }
}}>

If people want to write enhance callbacks that always do the default callback behavior, then they could create their own action that calls defaultBehavior without having to track any updates to the behavior.

Alternatives considered

One alternative is to keep the status quo and require the user to duplicate the default behavior if desired.

Another alternative is to call fallback_callback automatically after the returned callback runs, but also pass a cancel arg to the returned callback that would prevent that behavior if desired.

<form use:enhance={() => {
  loading = true;
  return ({action, result, cancel}) => {
    // invalidate & applyAction called automatically, unless cancel is called
    loading = false;
  }
}}>

This makes the default case simpler. However, this has a few downsides:

  • it’s a breaking change for people returning a callback that didn’t want invalidateAll and applyAction called
  • because we need to run the provided callback to find out if cancel was called, there isn’t a good way to run code after invalidation & applying the action has completed. Supplying defaultBehavior gives the user control over when invalidation happens.

Importance

would make my life easier

Additional Information

No response

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:10
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
repsac-bycommented, Sep 29, 2022

We will not rename cancel to preventDefault - this sounds unrelated to this issue.

I meant the other cancel() . The one specified in this issue in Alternatives considered, which is proposed to be passed to the result callback.

0reactions
dummdidummcommented, Sep 29, 2022

We will not rename cancel to preventDefault - this sounds unrelated to this issue.

The done function is interesting, but what happens if you call it and return a callback function?

<form use:enhance={( done ) => {
  loading = true;
  done(() => { 
      loading = false;
  });
  return () => {
     // what happens here? What happens with done?
  }
}}>

I think the semantics are more clear and easier to understand with an additional argument to the callback function

Read more comments on GitHub >

github_iconTop Results From Across the Web

Callback plugins - Ansible Documentation
Callback plugins enable adding new behaviors to Ansible when responding to events. By default, callback plugins control most of the output you see...
Read more >
JavaScript style for optional callbacks - Stack Overflow
Is checking if the callback is defined/function a good style or is there a better way? Example: function save (callback){ .....do stuff...... if( ......
Read more >
JavaScript Callback Functions – What are Callbacks in JS and ...
Callback functions are an important part of JavaScript and once you understand how callbacks work, you'll become much better in JavaScript.
Read more >
Use Ansible's YAML callback plugin for a better CLI experience
Use Ansible's YAML callback plugin for a better CLI experience. April 19, 2018. Ansible is a great tool for ... Ansible 2.5 default...
Read more >
Advanced Callbacks | Dash for Python Documentation | Plotly
Properties for callback_context · triggered : list of all the Input props that changed and caused the callback to execute. · inputs and...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found