skip to content

In Playwright component tests, how does calling update on a mounted component differ from mounting it again?

level: middleimportance: must knowfreq 44%

answer

  1. One keeps the instance, one replaces it
  2. Think about what survives the call
  3. Open panels and scroll offsets
  4. First-render effects run again, or not

basics

~20 s

update re-renders the component already on the page with new props, so its internal state — an open menu, scroll position, focus — survives. Mounting again builds a fresh instance and throws all of that away.

solid answer

~50 s

`await component.update(props)` re-renders the instance that is already mounted, so everything it had accumulated survives the change: an open dropdown stays open, a data grid keeps its scroll offset, focus stays where it was, uncontrolled inputs keep their values. Calling `mount` a second time creates a new instance, which means first-render effects run again and every bit of that state is gone. That difference decides which one a test should use. If the thing under test is a transition — a design-system grid receiving a new page of rows while scrolled, a toast handed a new message mid-animation — you must use `update`, because a re-mount can only ever show you two independent first renders. If the next scenario is unrelated, mount fresh so leftover state cannot make the assertion pass or fail for the wrong reason. In Playwright 1.63 `update` changes props on the same story; it does not reload the page.

code

typescript · 13 lines
typescript
import { test, expect } from '@playwright/test';

test('data grid keeps its open row menu across a page change', async ({ mount }) => {
  const grid = await mount('data-grid-default', { rows: firstPage });

  await grid.getByRole('row').nth(3).getByRole('button', { name: 'Row actions' }).click();
  await expect(grid.getByRole('menu')).toBeVisible();

  await grid.update({ rows: secondPage });

  await expect(grid.getByRole('menu')).toBeVisible();
  await expect(grid.getByRole('row')).toHaveCount(21);
});

go deeper

for a junior

Learn the one-line difference: update keeps the same component and gives it new props, mounting again starts over. If a test needs a clean slate, mount again rather than trying to reset by hand.

for a middle

Explain what survives and why. Nothing is torn down on update, so instance state persists and first-render effects do not re-run; a fresh mount discards all of it. Name a transition that only update can test.

for a senior

Use the difference diagnostically. A test that passes on re-mount but fails on update points at a prop read once at first render, and a test that only passes in file order points at leaked state.

for a principal

Set the convention for the suite. Decide when update chains are legitimate coverage of transitions and when they are hidden coupling, and make sure a failure in a long chain still tells the team which scenario broke.

## Two different operations that both put markup on the page Both routes end with a component rendered on the story page, and that is where the resemblance stops. - `await component.update(props)` re-renders the **instance already mounted** with a new set of props. - `await mount('toast-default', props)` again creates a **new instance** from the story. The distinguishing question is what happens to everything the component accumulated since it first rendered: an open dropdown, a scroll offset in a data grid, focus inside a date picker, the value of an uncontrolled input, an in-flight animation. `update` keeps it. A fresh mount does not. | Aspect | `update(props)` | Mounting again | |---|---|---| | Instance | the same one | a brand-new one | | Internal state | preserved | discarded | | First-render effects | not re-run | run again | | What it models | a prop change in a running app | a page arriving fresh | | Cost | one re-render | full render, and the teardown before it | ## Why state preservation is the point In a real application, most of what a component does happens on its second, tenth and hundredth render, not its first. A design-system data grid receives a new page of rows while the user is scrolled halfway down; a toast is handed a new message while it is mid-fade; a date picker gets a new minimum date while its month panel is open. Those transitions are where the bugs live, and a test that re-mounts between the two states cannot observe them at all — it only ever sees two independent first renders. `update` is what makes the transition testable: 1. Mount the story with the starting props. 2. Drive the component into the state that matters — open the panel, scroll the grid, focus a field. 3. Call `update` with the new props. 4. Assert on what should have survived, and on what should have changed. Step 4 is the assertion a fresh mount can never make, because after a fresh mount there is nothing that could have survived. ## When you actually want a fresh mount Re-mounting is not the weaker option; it is the right one when the scenario is genuinely independent. - The next scenario has nothing to do with the previous one, so carrying state over can only create false passes and false failures. - You are asserting first-render behaviour, such as an effect that must run exactly once or an initial focus target. - The previous scenario left the component in a state you would otherwise have to unwind by hand. - A prop change is not what you are testing at all, and the update chain would just be a slower way of writing setup. `unmount()` then a second `mount` gives the clean slate explicitly; a new test does the same thing with clearer failure output. ## Reading a failure of each kind The failure modes are different enough to be diagnostic: - An assertion that passes after a fresh mount but fails after `update` usually means the component does not react to the prop change — it read the prop once at first render and never again. - An assertion that passes after `update` but fails after a fresh mount usually means the behaviour depends on state left over from earlier steps, so the test was passing for the wrong reason. - A test that only fails when run after other tests in the same file is a state-leak signal: something was mounted and never unmounted, or an update chain ran further than the assertion assumed. ## The mechanics worth stating plainly `update` changes the **props** of what is already on the page. It is not a way to swap in a different story, it is not a reload of the story page, and it does not invalidate the locator you are holding — that locator is a query, so it resolves the new markup on the next use just as it resolved the old. The component goes through whatever its framework does for a prop change, which is precisely why the state survives: nothing is torn down, so nothing that lives in the instance is thrown away. Mounting again, by contrast, starts the story from the top, and everything from the previous instance is gone whether you wanted it gone or not.

  • Give a case where a re-mount would hide a real bug that update exposes.
    A data grid that reads its sort order only on first render. Re-mounting with new props renders correctly every time, so the suite is green. Updating the mounted instance with a new sort order leaves the old ordering on screen, which is exactly the bug users hit when the prop changes in a running app.
  • Your test only fails when other tests in the same file run first. What does that suggest?
    State leaking between scenarios. Something was mounted and never unmounted, or an update chain moved the component further than the later assertion assumed. Split the scenarios into their own tests with a fresh mount each, and the failure either disappears or becomes reproducible on its own.
  • Does update invalidate the locator you got from mount?
    No. That handle is a query, not a captured node, so after the re-render the next use resolves the new markup. You keep using the same variable, which is why an update-based test reads as one continuous interaction rather than as a re-acquisition of the component.

Update changes the props of an actor already on stage; re-mounting strikes the set and brings on a new cast that remembers nothing about the previous scene.

saying these in an interview costs you the question

  • Says update tears the component down and rebuilds it
  • Thinks a re-mount preserves scroll position or focus
  • Believes update reloads the whole story page
  • Uses long update chains where independent scenarios belong
  • Assumes first-render effects run again on every update