useJobForm
useJobForm(
input:UseJobFormProps):HookLoadingResult|UseJobFormReady
Headless hook for creating or updating an employee's job — title, hire date, S-Corp 2% shareholder flag, and Washington state workers' compensation fields.
Remarks
Companion hook to useCompensationForm. Jobs and their compensations are
separate entities in the Gusto API and this hook focuses exclusively on
the job side. Presence of jobId selects the verb:
| Hook config | Mode | API call |
|---|---|---|
{ employeeId, jobId } | update | PUT /v1/jobs/:jobId (with version) |
{ employeeId } (no jobId) | create | POST /v1/employees/:employeeId/jobs |
{} + submit employeeId | create | POST /v1/employees/:options.employeeId/jobs |
Creating a job auto-creates a stub compensation. To update the stub in the
same flow, capture currentCompensationUuid (and the compensation's
version from compensations[]) from the create response and thread them
into useCompensationForm.actions.onSubmit({ jobId, compensationId, compensationVersion }).
When the primary job's hireDate changes, secondary compensation effective
dates are corrected after the PUT; isPending stays true through that.
Example
import { useJobForm, SDKFormProvider } from '@gusto/embedded-react-sdk'
function JobForm({ employeeId }: { employeeId: string }) {
const job = useJobForm({ employeeId })
if (job.isLoading) return null
const { Fields } = job.form
return (
<form onSubmit={e => { e.preventDefault(); job.actions.onSubmit() }}>
<SDKFormProvider formHookResult={job}>
{Fields.Title && <Fields.Title label="Job title" />}
{Fields.HireDate && <Fields.HireDate label="Hire date" />}
{Fields.TwoPercentShareholder && (
<Fields.TwoPercentShareholder label="2% S-Corp shareholder" />
)}
</SDKFormProvider>
<button type="submit" disabled={job.status.isPending}>Save</button>
</form>
)
}
Props
UseJobFormProps
Configuration options for useJobForm.
Remarks
Presence or absence of jobId selects the API verb — see the jobId field
description. employeeId is optional so the hook can be composed alongside
an employee-creation step; supply it at submit time via
JobSubmitOptions.employeeId in that case.
| Property | Type | Description |
|---|---|---|
defaultValues? | Partial<JobFormData> | Pre-fill form values. Server data takes precedence on update mode. |
employeeId? | string | UUID of the employee whose job is being created or edited. May be omitted when the employee is created in the same submit chain — supply the value via JobSubmitOptions.employeeId at submit time. |
jobId? | string | Present → update mode (PUT /v1/jobs/:id with version). Omitted → create mode (POST /v1/employees/:id/jobs). |
optionalFieldsToRequire? | JobOptionalFieldsToRequire | Override fields that are optional on a given mode to be required. See JobOptionalFieldsToRequire. |
shouldFocusError? | boolean | Auto-focus the first invalid field on submit. Set to false when using composeSubmitHandler so submit-time focus is coordinated across multiple forms. Defaults to true. |
validationMode? | "onChange" | "onBlur" | "onSubmit" | "onTouched" | "all" | Passed through to react-hook-form. Defaults to 'onSubmit'. |
withHireDateField? | boolean | When false, hides Fields.HireDate (becomes undefined) and removes hireDate from schema validation. Supply the value via JobSubmitOptions.hireDate at submit time, or rely on the loaded job's existing value on update. Use this when the date is driven by external context rather than user input (e.g. the employee's startDate). Defaults to true. |
withTitleField? | boolean | When false, hides Fields.Title (becomes undefined), removes title from schema validation, and skips sending title on PUT/POST. Use this when another form owns the title field — e.g. compensation edit surfaces render the title via CompFields.Title because title lives on compensation in the API (job.title is just a denormalized snapshot of the primary comp's title). Defaults to true so the standalone job-creation flow still gathers a title for the create body. |
Returns
HookLoadingResult | UseJobFormReady
A HookLoadingResult while data is loading, or a UseJobFormReady once ready.
UseJobFormResult
UseJobFormResult =
HookLoadingResult|UseJobFormReady
Discriminated union returned by useJobForm.
Remarks
Branch on isLoading to narrow to either HookLoadingResult or
UseJobFormReady.
UseJobFormReady
Ready-state shape returned by useJobForm once data has loaded.
Remarks
Discriminated by isLoading: false. Extends
BaseFormHookReady with the job-specific data, status,
actions, and form.Fields shape.
| Property | Type | Description |
|---|---|---|
actions | object | Submit actions exposed by the hook. |
actions.onSubmit | (options?: JobSubmitOptions) => Promise<HookSubmitResult<Job> | undefined> | Validates the form, runs the appropriate create/update mutation, and resolves to a HookSubmitResult containing the saved job. Resolves to undefined on validation failure or mutation error. |
data | object | Job-specific data payload: the loaded job (if any), the employee's other jobs, the employee record, the active work address, and presentation flags for conditional fields. |
data.currentJob | Job | null | The job row loaded for update; null in create mode. |
data.currentWorkAddress | EmployeeWorkAddress | null | The employee's active work address, or null when none is set. |
data.employee | Employee | null | The loaded employee record, or null when employeeId was omitted. |
data.jobs | Job[] | undefined | All jobs for the employee, when employeeId is set. Useful for screen-level cross-checks across jobs. |
data.showStateWc | boolean | True when the active work-address state is WA; use this to decide whether to render StateWcCovered. Fields.StateWcClassCode is additionally gated on stateWcCovered === true, so most callers only need to check Fields.StateWcCovered / Fields.StateWcClassCode truthiness rather than this flag directly. |
data.showTwoPercentShareholder | boolean | True when the company is taxable as an S-Corp; use this to decide whether to render TwoPercentShareholder. |
errorHandling | HookErrorHandling | Error state and recovery actions. |
form | object | Form bindings: pre-bound field components, per-field metadata, submission values, and react-hook-form internals. |
form.Fields | JobFormFields | - |
form.fieldsMetadata | JobFieldsMetadata | - |
form.getFormSubmissionValues | () => JobFormData | undefined | - |
form.hookFormInternals | HookFormInternals<JobFormData> | - |
isLoading | false | Always false in this branch; discriminates from HookLoadingResult. |
status | object | Submission state. isPending is true while any in-flight mutation (including the secondary-compensation correction block) hasn't settled. mode reflects whether the next submit will create or update. |
status.isPending | boolean | - |
status.mode | "create" | "update" | - |
Fields
JobFormFields
Pre-bound field components exposed on useJobForm().form.Fields.
Remarks
Each property is either the field component or undefined. A field is
undefined when conditions for rendering it aren't met — see each member
for its visibility rule. Always null-check conditional fields (e.g.
{Fields.TwoPercentShareholder && <Fields.TwoPercentShareholder ... />})
before rendering.
| Property | Type | Description |
|---|---|---|
HireDate | ComponentType<HireDateFieldProps> | undefined | Bound to hireDate. Hire date picker. undefined when withHireDateField: false. |
StateWcClassCode | ComponentType<StateWcClassCodeFieldProps> | undefined | Bound to stateWcClassCode. Washington state workers' compensation risk class code select. undefined when the active work address is not in Washington or when stateWcCovered is false. |
StateWcCovered | ComponentType<StateWcCoveredFieldProps> | undefined | Bound to stateWcCovered. Washington state workers' compensation coverage radio group. undefined when the active work address is not in Washington (see data.showStateWc). |
Title | ComponentType<JobTitleFieldProps> | undefined | Bound to title. Job title text input. undefined when withTitleField: false. |
TwoPercentShareholder | ComponentType<TwoPercentShareholderFieldProps> | undefined | Bound to twoPercentShareholder. S-Corp 2% shareholder checkbox. undefined when the company is not taxable as an S-Corp (see data.showTwoPercentShareholder). |
HireDate
Bound to hireDate. Hire date picker. undefined when withHireDateField: false.
{form.Fields.HireDate && (
<form.Fields.HireDate
label="Hire date"
validationMessages={{ REQUIRED: '…' }}
/>
)}
HireDateFieldProps
HookFieldProps<DatePickerHookFieldProps<JobRequiredValidation>>
Props accepted by useJobForm's Fields.HireDate component.
| Property | Type | Description |
|---|---|---|
label | string | Visible label rendered above the field. |
FieldComponent? | ComponentType<DatePickerProps> | Replaces the default date picker UI component; must accept the same props as DatePickerProps. |
validationMessages? | ValidationMessages<JobRequiredValidation> | Custom error text keyed by validation error code. |
Also accepts description, formHookResult, maxDate, minDate, portalContainer from DatePickerHookFieldProps.
StateWcClassCode
Bound to stateWcClassCode. Washington state workers' compensation risk class code select. undefined when the active work address is not in Washington or when stateWcCovered is false.
{form.Fields.StateWcClassCode && (
<form.Fields.StateWcClassCode
label="State wc class code"
validationMessages={{ REQUIRED: '…' }}
/>
)}
StateWcClassCodeFieldProps
HookFieldProps<SelectHookFieldProps<JobRequiredValidation,WARiskClassCode>>
Props accepted by useJobForm's Fields.StateWcClassCode component.
| Property | Type | Description |
|---|---|---|
label | string | Visible label rendered above the field. |
placeholder | string | Placeholder text displayed when no option is selected. Required so empty dropdowns always communicate the action — pass an empty string only when a default value is guaranteed. |
FieldComponent? | ComponentType<SelectProps> | Replaces the default select UI component; must accept the same props as SelectProps. |
getOptionLabel? | (entry: WARiskClassCode) => string | Maps a raw option entry to its display label; when omitted, options use the labels provided by the hook. |
validationMessages? | ValidationMessages<JobRequiredValidation> | Custom error text keyed by validation error code. |
Also accepts description, formHookResult, portalContainer from SelectHookFieldProps.
StateWcCovered
Bound to stateWcCovered. Washington state workers' compensation coverage radio group. undefined when the active work address is not in Washington (see data.showStateWc).
{form.Fields.StateWcCovered && (
<form.Fields.StateWcCovered label="State wc covered" />
)}
StateWcCoveredFieldProps
HookFieldProps<RadioGroupHookFieldProps<never,boolean>>
Props accepted by useJobForm's Fields.StateWcCovered component.
| Property | Type | Description |
|---|---|---|
label | string | Visible label rendered above the field. |
FieldComponent? | ComponentType<RadioGroupProps> | Replaces the default radio group UI component; must accept the same props as RadioGroupProps. |
getOptionLabel? | (entry: boolean) => string | Maps a raw option entry to its display label; when omitted, options use the labels provided by the hook. |
Also accepts description, formHookResult from RadioGroupHookFieldProps.
Title
Bound to title. Job title text input. undefined when withTitleField: false.
{form.Fields.Title && (
<form.Fields.Title
label="Title"
validationMessages={{ REQUIRED: '…' }}
/>
)}
JobTitleFieldProps
HookFieldProps<TextInputHookFieldProps<JobRequiredValidation>>
Props accepted by useJobForm's Fields.Title component.
| Property | Type | Description |
|---|---|---|
label | string | Visible label rendered above the field. |
FieldComponent? | ComponentType<TextInputProps> | Replaces the default text input UI component; must accept the same props as TextInputProps. |
validationMessages? | ValidationMessages<JobRequiredValidation> | Custom error text keyed by validation error code. |
Also accepts description, formHookResult, placeholder, transform from TextInputHookFieldProps.
TwoPercentShareholder
Bound to twoPercentShareholder. S-Corp 2% shareholder checkbox. undefined when the company is not taxable as an S-Corp (see data.showTwoPercentShareholder).
{form.Fields.TwoPercentShareholder && (
<form.Fields.TwoPercentShareholder label="Two percent shareholder" />
)}
TwoPercentShareholderFieldProps
Props accepted by useJobForm's Fields.TwoPercentShareholder component.
| Property | Type | Description |
|---|---|---|
label | string | Visible label rendered above the field. |
FieldComponent? | ComponentType<CheckboxProps> | Replaces the default checkbox UI component; must accept the same props as CheckboxProps. |
Also accepts description, formHookResult from CheckboxHookFieldProps.
Validations
JobRequiredValidation
JobRequiredValidation =
"REQUIRED"
The validation error code a useJobForm field can produce.
Remarks
Currently a single literal — 'REQUIRED' — surfaced as the key in
validationMessages on each Fields.* component. Future schema additions
may extend the union.
Utility types
JobErrorCode
JobErrorCode =
"REQUIRED"
Union of every error code produced by the useJobForm schema.
JobErrorCodes
constJobErrorCodes:object
Validation error codes produced by the useJobForm schema.
Remarks
Use these constants as the keys in a field's validationMessages prop to
map an error code to a user-facing message.
Example
import { JobErrorCodes } from '@gusto/embedded-react-sdk'
<Fields.Title
label="Job title"
validationMessages={{ [JobErrorCodes.REQUIRED]: 'Job title is required' }}
/>
Type Declaration
| Name | Type |
|---|---|
REQUIRED | "REQUIRED" |
JobFieldsMetadata
| Field | Type |
|---|---|
hireDate | FieldMetadata |
stateWcClassCode | FieldMetadataWithOptions<WARiskClassCode> |
stateWcCovered | FieldMetadataWithOptions<boolean> |
title | FieldMetadata |
twoPercentShareholder | FieldMetadata |
Shape of the per-field metadata exposed at useJobForm().form.fieldsMetadata.
Remarks
Maps each field name in JobFormData to its presentation metadata —
including the registered name, whether the field is required or disabled,
and (for select-like fields) the option list.
JobFormData
Shape of the form values managed by useJobForm.
Remarks
Accepted as defaultValues on useJobForm and returned by
form.getFormSubmissionValues() once the form has validated. hireDate is
an ISO date string (YYYY-MM-DD) or null; stateWcCovered is a boolean
even though the radio group surfaces 'true' / 'false' strings during
input (the schema preprocessor coerces them).
Properties
| Property | Type | Description |
|---|---|---|
hireDate | string | null | The employee's hire date as an ISO 8601 string (YYYY-MM-DD), or null if unknown. |
stateWcClassCode | string | Washington state workers' compensation risk-class code. Required when stateWcCovered is true. |
stateWcCovered | boolean | Whether the employee is covered under Washington state workers' compensation insurance. |
title | string | The employee's job title (e.g. "Software Engineer"). |
twoPercentShareholder | boolean | Whether the employee owns 2 % or more of an S-corporation. Affects benefit-deduction tax treatment. |
JobOptionalFieldsToRequire
Override which fields are required on a given submission mode of useJobForm.
Remarks
Each mode key lists the fields that are optional by default for that mode
but should be promoted to required. stateWcClassCode is automatically
required when stateWcCovered is true and is not configurable here.
| Field | Required on create | Required on update | Configurable? |
|---|---|---|---|
title | Yes | No | Yes (on update) |
hireDate | Yes | No | Yes (on update) |
twoPercentShareholder | No | No | Yes (either mode) |
stateWcCovered | No | No | Yes (either mode) |
stateWcClassCode | When WC is covered | When WC is covered | No (auto) |
Example
const job = useJobForm({
employeeId,
jobId,
optionalFieldsToRequire: {
update: ['title', 'hireDate'],
},
})
Properties
| Property | Type | Description |
|---|---|---|
create? | ("stateWcClassCode" | "twoPercentShareholder" | "stateWcCovered")[] | Fields that can be required in create mode |
update? | ("title" | "hireDate" | "stateWcClassCode" | "twoPercentShareholder" | "stateWcCovered")[] | Fields that can be required in update mode |
JobSubmitOptions
Optional values supplied to useJobForm's actions.onSubmit at submit time.
Remarks
Use these when a value isn't sourced from a rendered field — typically
because the hook was configured with withHireDateField: false, or because
the employee being saved was created in the same submit chain and the
employeeId wasn't known at hook construction.
Properties
| Property | Type | Description |
|---|---|---|
employeeId? | string | Override the employeeId configured at hook construction. Useful when the employee is created in the same submit chain. |
hireDate? | string | Supply hireDate at submit time rather than via a rendered field. Use with withHireDateField: false for screens that derive hireDate from external context (e.g. the employee's startDate during onboarding). Falls back to the loaded job's hireDate on update mode when omitted; required (or sourced from a default) on create mode. |