React
Hook-based wrappers using useState / useEffect. Input is a plain value (not a getter) — dependencies tracked via JSON.stringify.
Setup
# metaxy.config.toml
[output]
react = "src/lib/rpc.react.ts"or via CLI
metaxy generate --react-output src/lib/rpc.react.tsuseQuery
import { useQuery } from './rpc.react';
import { rpc } from './client';
function UserList() {
const [page, setPage] = useState(1);
// Refetches when page changes
const users = useQuery(rpc, 'list_users', page, {
enabled: page > 0,
refetchInterval: 30000,
onSuccess: (data) => console.log(data),
});
// Void input
const time = useQuery(rpc, 'time');
return (
<>
{users.isLoading && <p>Loading...</p>}
{users.data?.map(u => <div key={u.id}>{u.name}</div>)}
<button onClick={() => users.refetch()}>Refresh</button>
</>
);
}useMutation
import { useMutation } from './rpc.react';
function CreateForm() {
const create = useMutation(rpc, 'create_user', {
onSuccess: (data) => console.log('Created:', data),
onError: (err) => console.error(err),
});
// Await the result
const handleSubmit = async () => {
try {
const user = await create.mutateAsync({ name: 'Alice' });
console.log('Created:', user);
} catch (err) {
// err is RpcError
}
};
return (
<>
<button onClick={handleSubmit} disabled={create.isLoading}>
{create.isLoading ? 'Creating...' : 'Create'}
</button>
{create.isError && <p>Error: {create.error?.message}</p>}
{create.isSuccess && <p>Created: {create.data?.name}</p>}
</>
);
}