---
title: Form data and state
description: Task guidance for form data and state.
version: 11.17.0
generatedAt: 2026-11-05T09:55:46.915Z
checksum: 090b7d977ba4be5e2c4c04d199a30a4048416c59f443a56985df2f80629d9c40
---

# Form data and state

## State management

While you can use a controlled approach to handle field or form state, we recommend a declarative approach where you keep the form state inside the data context instead of managing it with your own `useState` hooks (imperative).

- You do not need React **useState** to handle your form data.

How does this work?

Let's say you have a form with a `name` field. In order to tell, e.g., the `onSubmit` event what the data structure is, you define a declaration (`path`) about it right on the field itself:

```jsx
<Field.Name path="/name" />
```

Why call it `path`?

Because it can describe the structure of the data in several layers deep:

```jsx
<Field.Name path="/user/name" />
```

Which results in the following data structure:

```jsx
{
  user: {
    name: 'Hanna'
  }
}
```

Paths of fields (`path="/dataPath"`) must be unique to ensure proper error handling and data input. If Eufemia detects duplicate paths, it will print the following warning in the console: `Eufemia Path declared multiple times: /duplicatePath`.

This is called a [JSON Pointer](/web/forms/data-and-state/#what-is-a-json-pointer)—a standardized way of pointing to a specific part of a JavaScript/JSON object.

These JSON pointers are used to both read and write data and to validate form data.

### What is a JSON Pointer?

A [JSON Pointer](https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-03) is a string of tokens separated by `/` characters, these tokens either specify keys in objects or indexes in arrays.

```ts
const data = {
  foo: {
    bar: [
      {
        baz: 'value',
      },
    ],
  },
}
const pointer = '/foo/bar/0/baz' // points to 'value'
```

You can make these paths type-safe with autocomplete and compile-time checking — see [Type-checked paths](/web/forms/typed-paths/).

### Data handling

How do I handle complex data logic?

You can show or hide parts of your form based on your own logic. This is done by using the [Form.Visibility](/web/forms/Form/Visibility/) component (yes, it can even animate the visibility).

You can access and modify your form data with [Form.useData](/web/forms/Form/useData/), [Form.useDataValue](/web/forms/Form/useDataValue/), [Form.useDataWithoutSubscription](/web/forms/Form/useData/#formusedata), [Form.getData](/web/forms/Form/getData/), or [Form.setData](/web/forms/Form/setData/).

Use [Form.useDataValue](/web/forms/Form/useDataValue/) when rendered output depends on one form data path inside `Form.Handler`. Inside custom field or value components that render form data, use [useFieldProps](/web/forms/create-component/useFieldProps/) or [useValueProps](/web/forms/create-component/useValueProps/). They subscribe only to the component's own path, while `Form.useDataWithoutSubscription` is for non-subscribing imperative reads and writes, such as `getData()` in callbacks or effects.

Here is an example of how to use these methods:

```jsx
import { Form } from '@dnb/eufemia/extensions/forms'

const myFormId = 'unique-id' // or a function, object or React Context reference

function MyForm() {
  return (
    <Form.Handler id={myFormId}>
      <MyComponent />
    </Form.Handler>
  )
}

function MyComponent() {
  const companyName = Form.useDataValue('/companyName')

  const {
    getValue,
    update,
    remove,
    set,
    data,
    filterData,
    reduceToVisibleFields,
  } = Form.useData() // optionally provide an id or reference

  // Use Form.useDataWithoutSubscription() when you need
  // imperative helpers without subscribing to data changes.

  return <output>{companyName}</output>
}

// You can also use the setData:
Form.setData(myFormId, { companyName: 'DNB' })

// ... and the getData method whenever you need to:
const { getValue, data, filterData, reduceToVisibleFields } =
  Form.getData(myFormId)
```

- `getValue` will return the value of the given path.
- `update` will update the value of the given path.
- `remove` will remove the given path from the data context (fields will reapply their values afterwards).
- `set` will set the whole dataset.
- `data` will return the whole dataset (unvalidated).
- `filterData` will filter the data based on your own logic.
- `reduceToVisibleFields` will reduce the given data set to only contain the visible fields (mounted fields).

As you can see in the code above, you can even handle the state outside the `Form.Handler` context. You find more details on this topic in the [Form.useData](/web/forms/Form/useData/) documentation.


```tsx
const existingData = {
  companyName: 'DNB',
  companyOrganizationNumber: '123456789',
  postalAddressSelect: 'companyAddress'
};
function Component() {
  const {
    data
  } = Form.useData('company-form');
  console.log('State:', data);
  return <Form.Handler id="company-form" defaultData={existingData} onChange={console.log} onSubmit={console.log}>
              <Flex.Stack>
                <Form.MainHeading>Bedrift</Form.MainHeading>
                <Form.Card>
                  <Field.Name.Company path="/companyName" required />
                  <Field.OrganizationNumber path="/companyOrganizationNumber" required />
                  <Field.Selection path="/postalAddressSelect" label="Ønsket sted for tilsendt post" variant="radio">
                    <Field.Option value="companyAddress" title="Samme som forretningsadresse" />
                    <Field.Option value="other" title="Annet" />
                  </Field.Selection>
                </Form.Card>
                <Form.ButtonRow>
                  <Form.SubmitButton />
                </Form.ButtonRow>
              </Flex.Stack>
            </Form.Handler>;
}
render(<Component />);
```


### Filter data

In this section we will show how to filter out some data based on your own logic. You can filter data by any given criteria.

#### Concepts of filtering data

There are many ways to utilize `filterData`, here are some concepts to exclude a data entry:

- When a field is disabled.
- When a field is hidden.
- When a field has an error.
- When a field has a value that matches a given criteria.
- When a field has a path that starts with e.g. `_`.

Here is an example of how to filter data when a path starts with `_`:

```tsx
const filterDataHandler = ({ path }) => {
  if (/\/_/.test(path)) {
    // When returning false, the data entry will be left out
    return false
  }
}

render(
  <Form.Handler
    defaultData={{
      foo: 'foo',
      _bar: 'bar', // Will be excluded
    }}
    onSubmit={(data, { filterData }) => {
      const filteredData = filterData(filterDataHandler)
      console.log(filteredData) // Will be { foo: 'foo' }
    }}
  >
    <MyComponent />
  </Form.Handler>
)
```

#### How do I use it?

You can utilize the `filterData` method in:

- [Form.Handler](/web/forms/Form/Handler/#formhandler) component.
- [Form.useData](/web/forms/Form/useData/#formusedata) hook.
- [Form.useDataWithoutSubscription](/web/forms/Form/useData/#formusedata) hook.
- [Form.getData](/web/forms/Form/getData/#formgetdata) method.
- [Form.Visibility](/web/forms/Form/Visibility/#formvisibility) component.

You can provide either an object with the paths (1) or a handler (2).

Here is an example of how to filter data outlining the different ways to filter data:

```tsx
// 1. Method – by using paths (JSON Pointer)
const filterDataPaths = {
  '/foo': ({ value, data, props, error }) => value !== 'bar',
  '/foo': false, // Will exclude the field with the path "/foo"
  '/array/0': false, // Will exclude the first item of the array
  '/array/*/objectKey': false, // Will exclude all objects inside the array with a key of "objectKey"
}

// 2. Method – by using a handler.
// It will iterate over all fields and data entries regardless what path they have.
const filterDataHandler = ({ path, value, data, props, error }) => {
  if (/\/_/.test(path)) {
    // When returning false, the data entry will be left out
    return false
  }
}

const MyComponent = () => {
  const { filterData } = Form.useData()
  const filteredDataA = filterData(filterDataPaths)
  const filteredDataB = filterData(filterDataHandler)
  console.log(filteredDataA)
  console.log(filteredDataB)

  return <Field.String path="/foo" />
}

render(
  <Form.Handler>
    <MyComponent />
  </Form.Handler>
)
```

You may check out an [interactive example](/web/forms/Form/useData/#formusedata) of how to filter data.

#### Filter data during submit

When submitting data to the server, you might want to exclude data that has been hidden (unmounted) by the user. You have two built-in options to achieve this:

User entered data will always be stored internally in the data context, even if a [Field](/web/forms/all-fields/) is temporarily shown (mounted/unmounted).

##### The `reduceToVisibleFields` method

You can use the `reduceToVisibleFields` function to get only the data of visible (mounted) fields. Check out the [example](/web/forms/Form/Handler/demos/#reduce-your-data-to-visible-fields) in the demo section.

##### The `filterData` method

For filtering data during form submit you can use the `filterData` method given as a parameter to the `onSubmit` ([Form.Handler](/web/forms/Form/Handler/)) event callback:

```tsx
render(
  <Form.Handler
    onSubmit={(data, { filterData }) => {
      // Same method as in the previous example
      const filteredDataA = filterData(filterDataPaths)
      const filteredDataB = filterData(filterDataHandler)
      console.log(filteredDataA)
      console.log(filteredDataB)
    }}
  >
    <Field.String path="/foo" />
  </Form.Handler>
)
```

You may check out an [interactive example](/web/forms/Form/Handler/demos/#filter-your-data) of how to filter data during the submit event.

### Transforming data

Each [Field.\*](/web/forms/all-fields/) and [Value.\*](/web/forms/Value/) component supports transformer functions.

These functions allow you to transform the field value to a different format than it uses internally, and vice versa.

```tsx
<Field.String
  path="/myField"
  transformOut={transformOut}
  transformIn={transformIn}
/>
```

- `transformOut` (out of the `Field.*` component) transforms the internal value before it gets forwarded to the data context or returned as e.g. the `onChange` value parameter.
- `transformIn` (in to the `Field.*` or `Value.*` component) transforms the external value before it is displayed and used internally.


```tsx
const MyForm = () => {
  const transformToUpper = value => {
    return value?.toUpperCase();
  };
  const transformToLower = value => {
    return value?.toLowerCase();
  };
  return <Form.Handler onChange={console.log}>
              <Form.Card>
                <Field.String width="medium" label="Input value" placeholder="Type letters" path="/myField" transformIn={transformToUpper} transformOut={transformToLower} />

                <Value.String label="Output value" path="/myField" />
              </Form.Card>
            </Form.Handler>;
};
render(<MyForm />);
```


#### Complex objects in the data context

If you need to store complex objects in the data context instead of simple values like strings, numbers, or booleans, you can use transformer functions.

Suppose you want to store a country object instead of just a country code like `NO` or `SV` when using [Field.SelectCountry](/web/forms/feature-fields/SelectCountry/).

You can achieve this by using the `transformIn` and `transformOut` functions:

```tsx
import { Field } from '@dnb/eufemia/extensions/forms'
import type { CountryType } from '@dnb/eufemia/extensions/forms/Field/SelectCountry'

// From the Field (internal value) to the data context or event parameter
const transformOut = (internal, country) => {
  if (internal) {
    return country
  }
}

// To the Field (from e.g. defaultValue)
const transformIn = (external: CountryType) => {
  return external?.iso || 'NO'
}

const MyForm = () => {
  return (
    <Form.Handler>
      <Field.SelectCountry
        path="/country"
        transformIn={transformIn}
        transformOut={transformOut}
        defaultValue="NO"
      />

      <Value.SelectCountry path="/country" transformIn={transformIn} />
    </Form.Handler>
  )
}
```
