---
title: Cookbook | Synchronous Events with State
contributors:
  - mhevery
  - RumNCodeDev
---

import CodeSandbox, {CodeFile} from '../../../../components/code-sandbox/index.tsx';


# `sync$()` Synchronous Events (BETA)

Qwik processes events asynchronously. This means that some APIs such as `event.preventDefault()` and `event.stopPropagation()` do not work as expected. To work around this limitation, Qwik provides a `sync$()` API which allows you to process events synchronously. But `sync$()` comes with a few caveats:
1. `sync$()` can't close over any state.
2. `sync$()` can't call other functions which are declared in scope or imported.
3. `sync$()` is serialized into HTML and therefore we should be conscious of the size of the function.

A typical way to deal with these limitations is to split the event handling into two parts:
1. `sync$()` which is called synchronously and can call methods such as `event.preventDefault()` and `event.stopPropagation()`.
2. `$()` which is called asynchronously and can close over the state and call other functions, and has no restriction on the size.

Because `sync$()` can't access the state what is the best strategy to deal with it? The answer is to use element attributes to pass state into the `sync$()` function.
> **NOTE:** If you only need to prevent the default behavior, you can simply use the standard [`preventDefault:{eventName}`](/docs/components/events/#prevent-default) syntax. This is strictly for when you need to chain events together synchronously

## Example: `sync$()` with state

In this example, we have a behavior where we want to prevent the default behavior of the link based on some state. We do this by breaking the code into three parts:
1. `sync$()`: a synchronous portion that is kept to the minimum,
2. `$()`: an asynchronous portion that can be arbitrarily large, and can close over state,
3. `data-should-prevent-default`: an attribute on the element that is used to pass state into the `sync$()` function.


<CodeSandbox src="/src/routes/demo/cookbook/sync-event/"  style={{ height: '15em' }}>
</CodeSandbox>


<CodeFile src="/src/routes/demo/cookbook/sync-event/index.tsx">
```tsx
import { component$, useSignal, sync$, $ } from '@builder.io/qwik';

export default component$(() => {
  const shouldPreventDefault = useSignal(true);
  return (
    <div>
      <div>Sync Event:</div>
      <input
        type="checkbox"
        checked={shouldPreventDefault.value}
        onChange$={(e, target) =>
          (shouldPreventDefault.value = target.checked)
        }
      />{' '}
      Should Prevent Default
      <hr />
      <a
        href="https://google.com"
        target="_blank"
        data-should-prevent-default={shouldPreventDefault.value}
        onClick$={[
          sync$((e: MouseEvent, target: HTMLAnchorElement) => {
            if (target.hasAttribute('data-should-prevent-default')) {
              e.preventDefault();
            }
          }),
          $(() => {
            console.log(
              shouldPreventDefault.value ? 'Prevented' : 'Not Prevented'
            );
          }),
        ]}
      >
        open Google
      </a>
    </div>
  );
});
```
</CodeFile>
