# React

> Scroll reveal animations for React with the Reveal component and the useReveal hook: options, manual reveals, TypeScript, SSR and React Server Components.

`@awesome-reveal/react` needs React 18 or later. It has two APIs with the same options:

* The `Reveal` component renders one element and animates it.
* The `useReveal` hook animates your own element or component, with no wrapper.

To install the package, see [Getting started](/getting-started/).

## Entry points

| Import path                       | Contents                                                                            |
| --------------------------------- | ----------------------------------------------------------------------------------- |
| `@awesome-reveal/react`           | The `Reveal` component and the `useReveal` hook.                                    |
| `@awesome-reveal/react/keyframes` | The [built-in keyframes](/concepts/keyframes/), `defineKeyframes`, and their types. |

> **Tip**
>
> `@awesome-reveal/react/keyframes` does not import React, so you can call the factories in a Server Component. See [React Server Components](#react-server-components).

## The `Reveal` component

`Reveal` renders one element around its children. `as` sets the tag, and the default is `div`. `Reveal` gives its other props and its `ref` to that element:

```jsx
import { useRef } from "react";
import { Reveal } from "@awesome-reveal/react";
import { fade, slide } from "@awesome-reveal/react/keyframes";

function Hero() {
  const inputRef = useRef(null);

  return (
    <Reveal as="section" keyframes={slide()} className="hero" id="intro">
      <Reveal as="input" keyframes={fade()} ref={inputRef} />
    </Reveal>
  );
}
```

In TypeScript, the props and the `ref` type follow `as`.

The children animate together. To animate them one after the other, use [`stagger`](/concepts/options/#stagger).

## The `useReveal` hook

`useReveal(options)` returns `{ revealed, getProps }`:

* `revealed`: `true` while the element is revealed. With `once: false` or `when`, it can go back to `false`.
* `getProps(props?)`: merges the reveal into the props of the element. It returns the `ref`, the `style` with the hidden `opacity`, and `data-reveal`. Spread the result on the element.

```tsx
import { useReveal } from "@awesome-reveal/react";
import { fade } from "@awesome-reveal/react/keyframes";

function Card() {
  const { getProps } = useReveal({
    keyframes: fade(),
    threshold: 0.3,
  });

  return (
    <article {...getProps({ className: "card", style: { padding: 16 } })}>
      …
    </article>
  );
}
```

Pass your own `ref` and `style` to `getProps`, not next to the spread. `getProps` merges them. A `style` after the spread replaces the hidden style, and the element shows before the reveal.

`getProps` sets `data-reveal="hidden"` while the element is hidden. A `<noscript>` style can use it to show the element when JavaScript does not run. See [Pages without JavaScript](/concepts/accessibility/#pages-without-javascript).

Use `revealed` to run code after the reveal, for example in a `useEffect`.

To use `getProps` on your own component, forward the `ref` to an element. React 18 needs `forwardRef` for this.

With `stagger`, always render the children. Children that you render only when `revealed` is `true` do not animate.

The element type is `HTMLElement` by default. For another element, give the type, for example `useReveal<SVGSVGElement>()`.

## Options

`Reveal` and `useReveal` accept the [reveal options](/concepts/options/).

### Control the reveal manually

With `when`, your code controls the reveal, and nothing observes the viewport:

* `when={false}` hides the element.
* `when={true}` reveals the element and plays the animation.
* A change from `true` to `false` hides the element again.

```jsx
function Results({ data }) {
  return (
    <Reveal as="ul" when={data !== undefined} stagger={50}>
      {data?.map((item) => (
        <li key={item.id}>{item.name}</li>
      ))}
    </Reveal>
  );
}
```

With `when`, `threshold`, `rootMargin` and `once` have no effect. For the rest of the rules, such as the flash after hydration, see [Control the reveal manually](/concepts/options/#control-the-reveal-manually). For the effect of a changed option, see [Option changes](/concepts/options/#option-changes).

## TypeScript

`@awesome-reveal/react` exports these types:

* `RevealProps<T>`: the props of `Reveal`, where `T` is the tag in `as`.
* `RevealOptions`: the reveal options.
* `RevealState<T>`: the return value of `useReveal`.
* `RevealTargetProps<T>`: the return value of `getProps`.

`@awesome-reveal/react/keyframes` exports the keyframes types, such as `KeyframesFactory` and `SlideOptions`. See [Keyframes](/concepts/keyframes/).

## SSR

On the server, `Reveal` renders the element hidden, with `opacity: 0`, unless `when` is `true`. With `useReveal`, the element is hidden when you spread `getProps()` on it: it sets the hidden `style` and `data-reveal="hidden"`. The animation starts in the browser, when the element enters the viewport. If JavaScript does not run, the element stays hidden. To show it, add the [`<noscript>` style](/concepts/accessibility/#pages-without-javascript).

## React Server Components

`Reveal` and `useReveal` are client code, with the `"use client"` directive. You can render `Reveal` in a Server Component.

The keyframes factories do not import React. You can call them in a Server Component, and give the result to `Reveal`:

```jsx
import { Reveal } from "@awesome-reveal/react";
import { slide } from "@awesome-reveal/react/keyframes";

export default function Page() {
  return (
    <Reveal keyframes={slide({ direction: "left" })}>
      <h1>Rendered on the server</h1>
    </Reveal>
  );
}
```

A keyframes array is plain data, so React can send it from the server to the client. A function cannot go to a Client Component. Call the factory on the server. Then give its result to `Reveal`.

If you call `spring()` on the server, browsers without CSS `linear()` show the element with no animation. See [Springs](/concepts/keyframes/#springs).
