# React API

React API — Legend State documentation.

Source: https://legend.so/state/v2/react/react-api/

Legend State v2 documentation. **Archived version.** [Read the current documentation.](https://legend.so/state/v3/intro/introduction/)

## [Reading state](https://legend.so/state/v2/react/react-api/#reading-state)

### [observer](https://legend.so/state/v2/react/react-api/#observer)

`observer` is the suggested way of consuming observables for the best performance and safety.

It makes the whole component into an observing context - it automatically tracks observables for changes when `get()` is called, even from within hooks or helper functions.

The best option

Although observer looks like an HOC, it actually creates a Proxy around the component, with effectively no performance cost. So it is much more efficient than using multiple hooks, and much more efficient and safer than [enableReactTracking](https://legend.so/state/v2/usage/configuring#enablereacttracking).

`enableReactTracking` and `observer` can be used together - observer will optimize away the auto tracking behavior in favor of its more efficient tracking.

See [Tracking](https://legend.so/state/v2/usage/reactivity#observing-contexts) for more about when it tracks.

```jsx
import { observable } from "@legendapp/state"
import { observer } from "@legendapp/state/react"

const state$ = observable({ count: 0 })

const Component = observer(function Component() {
  // Accessing state automatically makes this component track changes to re-render
  const count = state$.count.get()

  // Re-renders whenever count changes
  return <div>{count}</div>
});
```

### [useSelector](https://legend.so/state/v2/react/react-api/#useselector)

`useSelector` computes a value and automatically listens to any observables accessed while running, and only re-renders if the computed value changes.

Props:

-   `selector`: Observable or computation function that listens to observables accessed while running
-   `options`: `{ suspense: boolean }`: Enable suspense when the value is a Promise and you're using it within React.Suspense.

```jsx
import { observable } from "@legendapp/state"
import { useSelector } from "@legendapp/state/react"

const state$ = observable({ selected: 1, theme })

const Component = ({ id }) => {
    // Only re-renders if the return value changes
    const isSelected = useSelector(() => id === state$.selected.get())

    // Get the raw value of an observable and listen to it
    const theme = useSelector(state$.theme)

    ...
}
```

#### [Using with React Suspense](https://legend.so/state/v2/react/react-api/#using-with-react-suspense)

Using `{ suspense: true }` as the second parameter makes the component work with Suspense. If the observable is a Promise, Suspense will render the fallback until it resolves to a value.

```jsx
import { useObservable, useSelector } from "@legendapp/state/react";
import { Suspense } from "react";

function Test({ state$ }) {
  const value = useSelector(state$, { suspense: true });
  return <div>{value}</div>;
}

export default function App() {
  const state$ = useObservable(
    new Promise((resolve) => {
      setTimeout(() => {
        resolve("hello");
      }, 1000);
    })
  );
  return (
    <div>
      <div>Suspense test</div>
      <Suspense fallback={<div>Loading...</div>}>
        <Test state$={state$} />
      </Suspense>
    </div>
  );
}
```

### [useObserve](https://legend.so/state/v2/react/react-api/#useobserve)

`useObserve` creates an [observe](https://legend.so/state/v2/usage/reactivity#observe) which you can use to take actions when observables change. This can be effectively similar to `useEffect` for observables, except that it runs when observables change and not because of a deps array changing.

Like `observe`, `useObserve` has an optional second callback parameter which will run after the selector, and does not track changes. This can be useful for observing an `event` or a single `observable`.

Note that `useObserve` runs during component render, not after render like `useEffect`. If you want an observer that runs after render, see [useObserveEffect](https://legend.so/state/v2/react/react-api/#useobserveeffect).

```jsx
import { event } from "@legendapp/state";
import { useObserve, useObservable, Reactive } from "@legendapp/state/react";

const eventUpdateTitle = event();

function ProfilePage() {
  const profile$ = useObservable({ name: "" });

  // This runs whenever profile changes
  useObserve(() => {
    document.title = `${profile$.name.get()} - Profile`;
  });

  // Observe a single observable with a callback when it changes
  useObserve(profile$.name, ({ value }) => {
    document.title = `${value} - Profile`;
  });

  // Observe an event with a callback when it changes
  useObserve(eventUpdateTitle, () => {
    document.title = `${profile$.name.get()} - Profile`;
  });

  return (
    <div>
      <span>Name:</span>
      <Reactive.input $value={profile$.name} />
    </div>
  );
}
```

### [useObserveEffect](https://legend.so/state/v2/react/react-api/#useobserveeffect)

`useObserveEffect` is the same as [useObserve](https://legend.so/state/v2/react/react-api/#useobserve) except that it doesn't run until the component is mounted.

## [Hooks for creating local state](https://legend.so/state/v2/react/react-api/#hooks-for-creating-local-state)

### [useObservable](https://legend.so/state/v2/react/react-api/#useobservable)

The `useObservable` hook can be used to create an observable within a React component. This can be useful when state is specific to the lifetime of the component, or to hold multiple values in local state.

Its observables will not be automatically tracked for re-rendering, so you can track them [the same as any other observable](https://legend.so/state/v2/react/react-introduction#use-observable-state).

As with

```jsx
import { observer, useObservable } from "@legendapp/state/react"

const Component = function Component() {
    const state$ = useObservable({
        title: 'Title',
        first: '',
        last: '',
        profile: {...}
    })

    const fullname$ = useObservable(() => `${state$.fname.get()} ${state$.lname.get()}`)

    return (
        <div>
            <div>{fullname$}</div>
            <Input text={state$.first} />
            <Input text={state$.last} />
            <Profile name={fullname$} />
        </div>
    )
}
```

### [useComputed](https://legend.so/state/v2/react/react-api/#usecomputed)

`useComputed` is like `useObservable` and creates a [computed](https://legend.so/state/v2/usage/reactivity#computed) observable.

```jsx
import { observable } from "@legendapp/state";
import { useComputed, Memo } from "@legendapp/state/react";

const state$ = observable({ test: 10, test2: 20 });

function Component() {
  const sum = useComputed(() => state$.test.get() + state$.test2.get());

  return <div>Sum: <Memo>{sum}</Memo></div>;
}
```

### [useObservableReducer](https://legend.so/state/v2/react/react-api/#useobservablereducer)

`useObservableReducer` works the same way as `useReducer` but sets an observable rather than triggering a render.

```jsx
import { useObservableReducer } from "@legendapp/state/react"

const Component = () => {
    // Only re-renders if the return value changes
    const isSelected$ = useObservableReducer()

    // Get the value of the reducer
    const theme = isSelected$.get()

    ...
}
```

### [Using with Context](https://legend.so/state/v2/react/react-api/#using-with-context)

You may prefer passing local state through Context rather than (or in addition to) having a global state. To do that you can simply add the observable to your Context as usual, and consume the Context from child component. The observable itself is a stable object so changing the value of an observable will not cause a re-render.

```jsx
import { createContext, useContext } from "react";
import { Memo, observer, useObservable } from "@legendapp/state/react";

const StateContext = createContext();

function App() {
  const state$ = useObservable({
    profile: {
      name: "",
    },
  });

  return (
    <StateContext.Provider value={state$}>
      <div>
        <Sidebar />
        <Main />
      </div>
    </StateContext.Provider>
  );
}

const Sidebar = function Sidebar() {
  // StateContext will never change so this will never cause a render
  const state$ = useContext(StateContext);

  // This component never re-renders, but name re-renders itself
  return (
    <div>
      Name: <Memo>{state$.profile.name}</Memo>
    </div>
  );
};
```

## [Miscellaneous hooks](https://legend.so/state/v2/react/react-api/#miscellaneous-hooks)

### [useMount](https://legend.so/state/v2/react/react-api/#usemount)

Using observable hooks we generally avoid the built-in hooks and dependency arrays, so we have a `useMount` hook for convenience, which is just `useEffect` under the hood.

```jsx
import { useMount } from "@legendapp/state/react";

const Component = () => {
  useMount(() => console.log("mounted"));
};
```

### [useUnmount](https://legend.so/state/v2/react/react-api/#useunmount)

Like the `useMount` hook, `useUnmount` is just `useEffect` under the hood.

```jsx
import { useUnmount } from "@legendapp/state/react";

const Component = () => {
  useUnmount(() => console.log("un-mounted"));
};
```

### [useEffectOnce](https://legend.so/state/v2/react/react-api/#useeffectonce)

This is `useEffect` with a workaround in development mode to make sure it only runs once.

```jsx
import { useEffectOnce } from "@legendapp/state/react";

const Component = () => {
  useEffectOnce(() => {
    console.log("mounted");
  }, []);
};
```

### [useMountOnce](https://legend.so/state/v2/react/react-api/#usemountonce)

This is `useMount` with a workaround in development mode to make sure it only runs once.

```jsx
import { useMountOnce } from "@legendapp/state/react";

const Component = () => {
  useMountOnce(() => console.log("mounted"));
};
```

### [useUnmountOnce](https://legend.so/state/v2/react/react-api/#useunmountonce)

This is `useEffect` with a workaround in development mode to make sure it only runs once.

```jsx
import { useUnmountOnce } from "@legendapp/state/react";

const Component = () => {
  useUnmountOnce(() => console.log("mounted"));
};
```

### [usePauseProvider](https://legend.so/state/v2/react/react-api/#usepauseprovider)

Version >= 2.1.1

This creates a React Context Provider with a `paused$` observable. Set `paused$` to `true` to pause all rendering from observable changes under the context, and set it `false` to resume. This applies to everything within Legend-State like observer, useSelector, Reactive, Memo, etc... But normal renders coming from React or other state is not affected.

[View Markdown](https://legend.so/state/v2/react/react-api.md)[Report a documentation correction](https://github.com/LegendApp/legend-docs/issues/new?title=Docs%3A+React+API&body=Page%3A+https%3A%2F%2Flegend.so%2Fstate%2Fv2%2Freact%2Freact-api%0A%0AWhat+is+incorrect+or+missing%3F%0A%0AExpected+behavior+or+supporting+source%3A%0A)
