Skip to content

feat: generate useMutation hooks for TanStack React Query plugin#3432

Merged
mrlubos merged 8 commits intohey-api:mainfrom
nmokkenstorm:feat/use-mutation-hooks
Mar 4, 2026
Merged

feat: generate useMutation hooks for TanStack React Query plugin#3432
mrlubos merged 8 commits intohey-api:mainfrom
nmokkenstorm:feat/use-mutation-hooks

Conversation

@nmokkenstorm
Copy link
Contributor

@nmokkenstorm nmokkenstorm commented Feb 22, 2026

I wanted to expose react/tanstack query mutations in the same way the useQuery works, so now you get useFooMutation() , no need to wire that through together. It greatly simplifies the consumption of mutation related code in a (private/corporate) codebase that I contribute to. We've been running a local fork with this feature.

The generated useMutation hooks reduce boilerplate in application/consumer code and save lot on small files that do manual wiring:


Before:

import { runStartMutation, runStopMutation } from './generated';
import { useMutation } from '@tanstack/react-query';

const { mutate: startRun, isPending: isStarting } = useMutation({ ...runStartMutation() });
const { mutate: stopRun, isPending: isStopping } = useMutation({ ...runStopMutation() });

After:

import { useRunStart, useRunStop } from './generated';

const { mutate: startRun, isPending: isStarting } = useRunStart();
const { mutate: stopRun, isPending: isStopping } = useRunStop();

Before:

import { connectMachineMutation } from './generated';
import { useMutation, useQueryClient } from '@tanstack/react-query';

const connectMutation = useMutation({
  ...connectMachineMutation(),
  onSuccess: async () => {
    await queryClient.invalidateQueries({ queryKey: getStatusQueryKey() });
  },
});

After:

import { useConnectMachine } from './generated';
import { useQueryClient } from '@tanstack/react-query';

const connectMutation = useConnectMachine({
  onSuccess: async () => {
    await queryClient.invalidateQueries({ queryKey: getStatusQueryKey() });
  },
});

One choice/tradeoff I made was to put the mutation options as a first positional argument, as the resulting mutation function seemed the neater way to pass in actual function arguments:

// `requestOptions: true`
const { mutate, isPending } = useCreateItem(
  { onSuccess: () => navigate('..') },
  { headers: { 'X-Custom': 'value' } },
);

Without this ordering, every consumer that wants to pass onSuccess has to write:

const { mutate, isPending } = useCreateItem(undefined, {
  onSuccess: () => navigate('..'),
});

which was the more naive implementation I had at first, but the undefined everywhere for the positional arguments was bothering me. Now you set up your request stuff in the hook call, and request data in the execution of the resulting function, which seemed the more ergonomic approach.

This PR is first of three, as mentioned I am running a fork with some additional things for my project. I want use this as a starting point to get some discussion going and figure out how to collaborate / if a PR like this is appreciated or not. The actual code diff isn't that big, it's mostly wiring through a parameter that works the same way for useQuery and the snapshot tests.

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@pullfrog
Copy link

pullfrog bot commented Feb 22, 2026

Leaping into action...

Pullfrog  | View workflow run | Using OpenCode | Triggered by Pullfrogpullfrog.com𝕏

@changeset-bot
Copy link

changeset-bot bot commented Feb 22, 2026

🦋 Changeset detected

Latest commit: 304a86f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@hey-api/openapi-ts Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link

vercel bot commented Feb 22, 2026

@nmokkenstorm is attempting to deploy a commit to the Hey API Team on Vercel.

A member of the Team first needs to authorize it.

@dosubot dosubot bot added size:XXL This PR changes 1000+ lines, ignoring generated files. feature 🚀 Feature request. labels Feb 22, 2026
@nmokkenstorm
Copy link
Contributor Author

⚠️ No Changeset found

Latest commit: e4f4189

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.
This PR includes no changesets

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

It probably should actually? It's a non-breaking feature addition, happy to take some pointers re: changesets setup.

@codecov
Copy link

codecov bot commented Feb 22, 2026

Codecov Report

❌ Patch coverage is 6.45161% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.25%. Comparing base (ce29020) to head (304a86f).
⚠️ Report is 10 commits behind head on main.

Files with missing lines Patch % Lines
...src/plugins/@tanstack/query-core/v5/useMutation.ts 11.11% 14 Missing and 2 partials ⚠️
...api-ts/src/plugins/@tanstack/react-query/config.ts 0.00% 8 Missing and 2 partials ⚠️
...i-ts/src/plugins/@tanstack/query-core/v5/plugin.ts 0.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3432      +/-   ##
==========================================
- Coverage   40.31%   40.25%   -0.06%     
==========================================
  Files         483      484       +1     
  Lines       17560    17591      +31     
  Branches     5317     5329      +12     
==========================================
+ Hits         7080     7082       +2     
- Misses       8427     8451      +24     
- Partials     2053     2058       +5     
Flag Coverage Δ
unittests 40.25% <6.45%> (-0.06%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Member

@mrlubos mrlubos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not much I can say, this pull request looks very clean!

@nmokkenstorm
Copy link
Contributor Author

Not much I can say, this pull request looks very clean!

Thank you 🫶🏻 it's a relatively simple change that composes well and saves my personally quite a bit of boilerplate in application code so I thought I'd share.

I do need a bit of time to figure out the testing strategy/merge checks, lmk if you have any tips there?

@mrlubos
Copy link
Member

mrlubos commented Feb 24, 2026

@nmokkenstorm It looks good to me. You can run tests locally if you'd like to confirm. That heavy typecheck step is flaky in CI, I'm meant to split those tests because it's gotten too large, but other things are more important

@nmokkenstorm
Copy link
Contributor Author

I'll fix what we discussed, run some local tests, report what I did and then we can continue 👍

@nmokkenstorm
Copy link
Contributor Author

@mrlubos looks good on my end!

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 3, 2026

Open in StackBlitz

@hey-api/codegen-core

npm i https://pkg.pr.new/@hey-api/codegen-core@3432

@hey-api/json-schema-ref-parser

npm i https://pkg.pr.new/@hey-api/json-schema-ref-parser@3432

@hey-api/nuxt

npm i https://pkg.pr.new/@hey-api/nuxt@3432

@hey-api/openapi-ts

npm i https://pkg.pr.new/@hey-api/openapi-ts@3432

@hey-api/shared

npm i https://pkg.pr.new/@hey-api/shared@3432

@hey-api/types

npm i https://pkg.pr.new/@hey-api/types@3432

@hey-api/vite-plugin

npm i https://pkg.pr.new/@hey-api/vite-plugin@3432

commit: c94211f

@dosubot dosubot bot added the lgtm This PR has been approved by a maintainer label Mar 3, 2026
@mrlubos mrlubos merged commit 262798e into hey-api:main Mar 4, 2026
4 of 22 checks passed
@hey-api hey-api bot mentioned this pull request Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature 🚀 Feature request. lgtm This PR has been approved by a maintainer size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants