> Markdown version of [React](https://vaadin.com/docs/next/flow/integrations/react). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# Using React Components in Flow

[React](https://reactjs.org/) is a popular JS-based frontend UI library with many components and is widely adopted. This page is the API reference for integrating React components with Flow by using an intermediate adapter Web Component. For a step-by-step guide, see [Wrap a React Component](https://vaadin.com/docs/next/building-apps/components/wrap-react-component.md).

The integration involves two parts: a server-side Java adapter component and a client-side TypeScript/React adapter. The examples here use the [React Colorful](https://omgovich.github.io/react-colorful/) color picker component.

## <a id="server-side"></a>Server-Side Adapter Java Component

For the server-side part of the integration, create a Java class that extends from `ReactAdapterComponent` like so:

`RgbaColorPicker.java`

```java
@NpmPackage(value = "react-colorful", version = "5.6.1") // (1)
@JsModule("./demo/flow/integration/react/rgba-color-picker.tsx") // (2)
@Tag("rgba-color-picker") // (3)
public class RgbaColorPicker extends ReactAdapterComponent {


}
```

1. Since this will integrate a third-party React component, the `@NpmPackage` annotation is added to be installed from npm.

2. The client-side part of the integration (i.e., the adapter Web Component) is yet to be defined and implemented in TypeScript. Therefore, you’ll need a separate file for it. Although this file will be created later, the `@JsModule` annotation is added here to import it.

3. The `@Tag` annotation defines the DOM element name of the adapter Web Component (see below).

### <a id="java-react-states-synchronized"></a>Java & React States Synchronized

The Web Component adapter allows the state to be sent from Java to React and back by using named properties and events in the intermediate Web Component. On the server side, the `ReactAdapterComponent` class provides the following APIs for synchronizing the state with the adapter Web Component:

- `setState(String, T)` method is for sending the state from the server;

- `getState(String, Class<T>)` method is used for retrieving the current value from the client; and

- `addStateChangeListener(String, Class<T>, Consumer<T>)` adds a server-side listener for state changes in the client.

You can use these methods to implement Java component property getters and setters, and event APIs. The example here uses the synchronized state for the `getColor()` and `setColor(RgbaColor)` accessor methods:

`RgbaColorPicker.java`

```java
public class RgbaColorPicker extends ReactAdapterComponent {

    public RgbaColor getColor() {
        return getState("color", RgbaColor.class);
    }

    public void setColor(RgbaColor color) {
        setState("color", color);
    }

}
```

> **Note: Setting Initial Value**
>
> Call `setState` from the Java constructor to ensure the state is initialized from Java. Doing so enables `@PreserveOnRefresh` to work correctly.

Next, invoke `setColor(RgbaColor)` from the constructor to define the initial state like so:

`RgbaColorPicker.java`

```java
public class RgbaColorPicker extends ReactAdapterComponent {

    public RgbaColorPicker() {
        setColor(new RgbaColor(255, 0, 0, 0.5));
    }

}
```

Also, you’ll need to add the `addColorChangeListener(Consumer<T>)` state change callback:

`RgbaColorPicker.java`

```java
public class RgbaColorPicker extends ReactAdapterComponent {

    public void addColorChangeListener(
            SerializableConsumer<RgbaColor> listener) {
        addStateChangeListener("color", RgbaColor.class, listener);
    }

}
```

### <a id="using-non-primitive-types"></a>Using Non-Primitive Types

On the client, the React state can be any JS value. To support that, the methods above accept Java boxed primitive types, as well as Beans and collections that are representable with JSON.

In the example here, the component has the `color` property, which is a JS object with the following format:

```typescript
type RgbaColor = {
  r: number;
  g: number;
  b: number;
  a: number;
};
```

For representing such object types in Java, an easy option is to define a Bean using a record. The following example shows the `RgbaColor` bean, which was used in the `RgbaColorPicker` example above:

`RgbaColor.java`

```java
public record RgbaColor(int r, int g, int b, double a) {

    @Override
    public String toString() {
        return "{ r: %s, g: %s, b: %s, a: %s }".formatted(r, g, b, a);
    }

}
```

## <a id="client-side"></a>Client-Side Adapter Web Component

Flow provides the `ReactAdapterElement` TypeScript class for implementing Web Components that render with React.

The following example uses `ReactAdapterElement` to create the `<rgba-color-picker>` Web Component, which renders the `<RgbaColorPicker>` third-party React component in the client:

`rgba-color-picker.tsx`

```jsx
class RgbaColorPickerElement extends ReactAdapterElement {
  protected override render(hooks: RenderHooks): ReactElement | null { // (1)
    const [color, setColor] = hooks.useState<RgbaColor>('color'); // (2)

    return <RgbaColorPicker color={color} onChange={setColor} />; // (3)
  }
}

customElements.define('rgba-color-picker', RgbaColorPickerElement); // (4)
```

1. The main part of the Web Component is the `render(RenderHooks)` callback, which defines the rendering using React JSX tags. You could also define state and events using the APIs provided with the `hooks` argument.

2. This calls `hooks.useState<RgbaColor>("color")` to define the `color` property of the adapter Web Component that is to be used for synchronizing the state with the server.

3. The JSX rendering uses the adapter state (i.e., `color` and `setColor`) with the `<RgbaColorPicker>` React component, following the third-party component’s API.

4. As usual with Web Components, the JS class is registered for its DOM element name using `CustomElements.define()` standard web API.

### <a id="renderhooks-apis"></a>RenderHooks APIs

The `RenderHooks` render callback argument provides the following two methods:

- `useState<T>(string)` method defines and uses a named state JS property of the adapter Web Component; and

- `useCustomEvent<T | undefined>(string, CustomEventInit<T>)` method returns a simple-to-use callback that dispatches a Custom Event with the given name on the adapter Web Component.

Firing a CustomEvent

```jsx
interface PersonData {
    name: string,
    age?: number
}

class PersonDataElement extends ReactAdapterElement {
    protected override render(hooks: RenderHooks): ReactElement | null {
        const fireUpdateEvent = hooks.useCustomEvent<PersonData>("update",
            // optional event detail:
            { detail: { name: "John", age: 42 } }
        );
        return (
            <>
                <VerticalLayout>
                    <Button onClick={() => fireUpdateEvent({ name: "Mike" })}>
                        Update
                    </Button>
                </VerticalLayout>
            </>
        );
    }
}
```

When the user action is not related to a state change, you could use this hook and subscribe to the event in Java:

Listening for a CustomEvent

```java
public void addPersonDataUpdateListener() {
    getElement().addEventListener("update", event -> {
        JsonObject person = event.getEventData();
        // person update code goes here...
    }).addEventData("event.detail");
}
```

## <a id="adding-flow-components-to-react-component"></a>Adding Flow Components to React Component

It’s possible to put Flow `Component` elements inside a React component implemented with `ReactAdapterElement`. You could generate a `RouterLayout` in React that has a navigation menu and the Flow route content on the right side. See [RouterLayout Interface](https://vaadin.com/docs/next/flow/routing/layout.md) for more information.

Create a `ReactAdapterComponent` that implements the `RouterLayout` interface so that the `showRouterLayoutContent` is appended into the content element from `getContentElement(String)`.

`RouterLinks` are added to a `Div` that’s bound to the `menu` content element on the client.

Server Router Layout

```java
@JsModule("./ReactRouterLayout.tsx")
@Tag("react-router-layout")
public class ReactRouterLayout extends ReactAdapterComponent implements RouterLayout {

    public ReactRouterLayout() {
        Div links = new Div(
                new RouterLink("Main view", MainView.class),
                new Div(),
                new RouterLink("Information", InfoView.class)
        );
        links.getStyle().setMargin("10px");
        getContentElement("menu").appendChild(links.getElement());
    }

    @Override
    public void showRouterLayoutContent(HasElement content) {
        if (content != null) {
            // Bind the flow element to the 'flowContent' element on the client
            getContentElement("flowContent")
                    .appendChild(Objects.requireNonNull(content.getElement()));
        }
    }
}
```

On the client, there are two places for Flow components to bind: one for `menu`; and one for `flowContent`, using the `userContent(string)`.

Client Router Layout

```jsx
class ReactRouterLayoutElement extends ReactAdapterElement {
    protected render(hooks: RenderHooks): React.ReactElement | null {
        // create content element for name attribute 'menu'
        const menu = hooks.useContent('menu');
        // create content element for name attribute 'flowContent'
        const content = hooks.useContent('flowContent');

        return <div style={{display: 'flex', flex: 1, flexDirection: 'row', height: '100%'}}>
            <div style={{flex: 1}}>{menu}</div>
            <div style={{flex: 5}}>{content}</div>
        </div>;
    }
}

customElements.define('react-router-layout', ReactRouterLayoutElement);
```

## <a id="wrap-react-component"></a>Wrapping a React Input Component into a Flow Field Component

When integrating React components into Vaadin applications, one common requirement is to enable these components to participate in Vaadin’s data binding and form handling. This can be accomplished by wrapping the React component in a Vaadin component that extends `AbstractSinglePropertyField`. This allows the React component to be used like any other field in Vaadin, making it compatible with the `Binder` API.

This integration process involves two main parts: creating a Java class for the server-side adapter component; and developing a client-side adapter using TypeScript and React.

This process is demonstrated in the next sections using a simple React text input component as an example.

### <a id="create-client-side-react-component"></a>Create Client-Side React Component

First, define your React component. For this example, assume a simple text input component.

```jsx
// File: frontend/react-text-input.tsx

import React, { useState } from 'react';
import { ReactAdapterElement, type RenderHooks } from 'Frontend/generated/flow/ReactAdapter';

class ReactTextInputElement extends ReactAdapterElement {
    constructor() {
        super();
    }

    protected override render(hooks: RenderHooks): React.ReactElement | null {
        const [value, setValue] = hooks.useState<string>('value');

        const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
            setValue(event.target.value);
            this.dispatchEvent(new CustomEvent('value-changed', { detail: { value: event.target.value } }));
        };

        return (
            <div>
                <input type="text" value={value} onChange={handleChange} />
                <span>{value?.length} characters</span>
            </div>
        );
    }
}

customElements.define('react-text-input', ReactTextInputElement);
```

### <a id="server-side-vaadin-component-wrapping-the-react-component"></a>Server-Side Vaadin Component Wrapping the React Component

Next, create a Vaadin component that wraps the React component and extends `AbstractSinglePropertyField`.

```java
// Package: com.example.application.ui

import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.AbstractSinglePropertyField;

@Tag("react-text-input")
@JsModule("./react-text-input.tsx")
public class ReactTextField extends AbstractSinglePropertyField<ReactTextField, String> {
    public ReactTextField() {
        super("value", "", false);
    }
}
```

### <a id="using-react-component-in-a-vaadin-form"></a>Using React Component in a Vaadin Form

Now, you can use `ReactTextField` like any other Vaadin component within a form:

```java
Binder<Person> binder = new Binder<>(Person.class);
ReactTextField reactTextField = new ReactTextField();

binder.forField(reactTextField).bind(Person::getName, Person::setName);

add(reactTextField);
```
