> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/preactjs/preact/llms.txt
> Use this file to discover all available pages before exploring further.

# setupRerender

> Enable synchronous rendering for testing

The `setupRerender` function configures Preact to render synchronously, making it easier to test components without dealing with asynchronous behavior.

## Signature

```typescript theme={null}
function setupRerender(): () => void
```

Returns a function that manually triggers pending renders.

## How it works

From [test-utils/src/index.js:7-11](https://github.com/preactjs/preact/blob/main/test-utils/src/index.js#L7-L11):

```javascript theme={null}
export function setupRerender() {
  options.__test__previousDebounce = options.debounceRendering;
  options.debounceRendering = cb => (options.__test__drainQueue = cb);
  return () => options.__test__drainQueue && options.__test__drainQueue();
}
```

The function:

1. Saves the original `options.debounceRendering` function
2. Replaces it with a version that captures the render callback
3. Returns a function that executes the captured callback

This allows you to control exactly when renders happen in your tests.

## Usage

### Basic setup

```javascript theme={null}
import { setupRerender, teardown } from 'preact/test-utils';
import { afterEach } from 'vitest';

const rerender = setupRerender();

afterEach(() => {
  teardown();
});

test('my test', () => {
  // Render component
  render(<MyComponent />, container);
  
  // Manually flush renders
  rerender();
  
  // Now you can assert
  expect(container.textContent).toBe('Hello');
});
```

### With state updates

```javascript theme={null}
import { useState } from 'preact/hooks';
import { setupRerender, teardown } from 'preact/test-utils';

function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <span>{count}</span>
      <button onClick={() => setCount(c => c + 1)}>+</button>
    </div>
  );
}

test('counter increments', () => {
  const rerender = setupRerender();
  const container = document.createElement('div');
  
  render(<Counter />, container);
  rerender();
  expect(container.querySelector('span').textContent).toBe('0');
  
  container.querySelector('button').click();
  rerender();
  expect(container.querySelector('span').textContent).toBe('1');
  
  teardown();
});
```

### Test suite setup

```javascript theme={null}
import { setupRerender, teardown } from 'preact/test-utils';
import { beforeEach, afterEach, test } from 'vitest';

let rerender;

beforeEach(() => {
  rerender = setupRerender();
});

afterEach(() => {
  teardown();
});

test('test 1', () => {
  // Use rerender
});

test('test 2', () => {
  // Use rerender
});
```

## When to use

### Use setupRerender when:

* You want fine-grained control over rendering
* You're not using `act()`
* You're writing low-level test utilities
* You need to test render timing

### Use act instead when:

* You want automatic effect flushing
* You're testing user interactions
* You're testing async code
* You want compatibility with React testing patterns

<Note>
  Most tests should use `act()` instead of `setupRerender()` directly. The `act()` function calls `setupRerender()` internally and also handles effects.
</Note>

## teardown function

Always call `teardown()` after using `setupRerender()` to restore Preact's default behavior:

```javascript theme={null}
import { teardown } from 'preact/test-utils';

afterEach(() => {
  teardown();
});
```

From [test-utils/src/index.js:117-130](https://github.com/preactjs/preact/blob/main/test-utils/src/index.js#L117-L130):

```javascript theme={null}
export function teardown() {
  if (options.__test__drainQueue) {
    // Flush any pending updates leftover by test
    options.__test__drainQueue();
    delete options.__test__drainQueue;
  }

  if (typeof options.__test__previousDebounce != 'undefined') {
    options.debounceRendering = options.__test__previousDebounce;
    delete options.__test__previousDebounce;
  } else {
    options.debounceRendering = undefined;
  }
}
```

The teardown function:

1. Flushes any pending renders
2. Restores the original `debounceRendering` function
3. Cleans up test state

<Warning>
  Forgetting to call `teardown()` can cause test interference where one test's render behavior affects another.
</Warning>

## Example: Testing framework integration

```javascript theme={null}
import { setupRerender, teardown } from 'preact/test-utils';

export function setupPreactTests() {
  let rerender;
  
  beforeEach(() => {
    rerender = setupRerender();
  });
  
  afterEach(() => {
    teardown();
  });
  
  return {
    render(vnode, container) {
      render(vnode, container);
      rerender();
    },
    
    update(callback) {
      callback();
      rerender();
    }
  };
}

// Usage
const { render: renderSync, update } = setupPreactTests();

test('my test', () => {
  renderSync(<Component />, container);
  
  update(() => {
    button.click();
  });
  
  expect(container.textContent).toBe('Updated');
});
```

## Best practices

### Always clean up

```javascript theme={null}
// ✅ Good
afterEach(() => {
  teardown();
});

// ❌ Bad - will leak into other tests
const rerender = setupRerender();
// No cleanup!
```

### Flush after renders

```javascript theme={null}
// ✅ Good
render(<Component />, container);
rerender();
expect(container.textContent).toBe('Hello');

// ❌ Bad - render may not be complete
render(<Component />, container);
expect(container.textContent).toBe('Hello');
```

### Use act for effects

```javascript theme={null}
// ✅ Good for effects
await act(() => {
  render(<ComponentWithEffect />, container);
});

// ❌ Bad - setupRerender doesn't flush effects
const rerender = setupRerender();
render(<ComponentWithEffect />, container);
rerender(); // Effects not flushed!
```

## Related

* [act API](/api/test-utils/setup-scratch)
* [Test utils overview](/api/test-utils/overview)
* [Testing guide](/advanced/testing)
* [Options API](/advanced/options-api)
