# Form
Use this component when you want to collect input from users. It provides a structure for various input fields and controls, such as text fields, checkboxes, and buttons. It also integrates with the native Contextual Save Bar to handle form submission and reset actions.
### Simple form implementation

```tsx
import React, { useCallback, useState } from 'react';
import {
  reactExtension,
  Form,
  TextField,
} from '@shopify/ui-extensions-react/admin';

export default reactExtension("admin.product-details.block.render", () => <App />);

function App() {
  const [value, setValue] = useState("");
  const [error, setError] = useState('');

  const onSubmit = useCallback(
    async () => {
      // API call to save the values
      const res = await fetch('/save', {method:'POST', body: JSON.stringify({name: value})});
      if (!res.ok) {
        const json = await res.json();
        const errors = json.errors.join(',');
        setError(errors);
      }
    },
    [value]
  );

  const onReset = useCallback(async () => {
     // Reset to initial value
     setValue('')
     // Clear errors
     setError('')
  }, []);

  const onInput = useCallback((nameValue) => {
    if (!nameValue) {
      setError("Please enter a name.");
    }
  }, [])

  // Field values can only be updated on change when using Remote UI.
  const onChange = useCallback((nameValue) => {
    setValue(nameValue);
  }, [])


  return (
    <Form id="form" onSubmit={onSubmit} onReset={onReset}>
      <TextField label="name" value={value} onInput={onInput} onChange={onChange} error={error} />
    </Form>
  );
}

```

```js
import {
  extend,
  Form,
  TextField,
} from '@shopify/ui-extensions/admin';

extend('admin.product-details.block.render', (root) => {
  let name = '';

  const textField = root.createComponent(
    TextField,
    {
      label: 'name',
      value: name,
      onChange: (value) => {
        textField.updateProps({value});
        name = value;
      },
    }
  );

  const onSubmit = async () => {
    // API call to save the values
    const res = await fetch('/save', {method:'POST', body: JSON.stringify({name})});
    if (!res.ok) {
      const json = await res.json();
      // The Host can catch these errors and do something with them.
      throw Error(`There were errors: ${json.errors.join(',')}`);
    }
  };

  const onReset = async () => {
    name = '';
  };

  const form = root.createComponent(
    Form,
    {onSubmit, onReset}
  );

  form.appendChild(textField);
  root.appendChild(form);
});

```


## FormProps

### FormProps

### id
A unique identifier for the form.
### onReset
A callback that is run when the form is reset.
### onSubmit
A callback that is run when the form is submitted.
## Related
- [TextField](/docs/api/admin-extensions/components/forms/textfield)
- [NumberField](/docs/api/admin-extensions/components/forms/numberfield)
- [EmailField](/docs/api/admin-extensions/components/forms/emailfield)