# React API

React API — Legend State documentation.

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

Legend State v3 documentation. Current documentation version.

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

### [useValue](https://legend.so/state/v3/react/react-api/#usevalue)

Migration from useSelector or use$

In previous versions this was called 'useSelector' or 'use$'. If you were using `useSelector` or `use$` it will still work for a while, but we suggest changing them to `useValue` as we'll remove `useSelector` and 'use$' in a later version. Many people were unsure of what a "selector" was so it was unclear what it did. Plus, `useValue` is shorter 😀

Migration from use$

`use$` was not compatible with React Compiler, so if you're using Compiler we strongly suggest migrating to `useValue`.

`useValue` computes a value and automatically listens to any observables accessed while running, and only re-renders if the computed value changes. This can take either an observable or a function that consumes observables.

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 { useValue } from "@legendapp/state/react"

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

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

    // Get the raw value of an observable and re-render when it changes
    const theme = useValue(state$.theme)

    ...
}
```

#### [Using with React Suspense](https://legend.so/state/v3/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 non-undefined value.

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

function Test({ state$ }) {
  const value = useValue(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>
  )
}
```

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

`observer` is a good optimization if you consume many observables in one component. It inserts a single tracking hook into the component. Calls to `useValue` with an observable argument and without suspense share that tracking context, reducing the number of hooks. Calls with a computation function still use their own hook.

Although observer looks like an HOC, it creates a Proxy around the component and memoizes it. It tracks observable access during rendering in a shared context.

> In previous versions this allowed calling `get()` directly within components, but that is discouraged as of 3.0.0-beta.20. See [migrating](https://legend.so/state/v3/other/migrating) for more info.

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

```jsx
import { observable } from "@legendapp/state"
import { observer, useValue } 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 = useValue(state$.count)

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

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

`useObserve` creates an [observe](https://legend.so/state/v3/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/v3/react/react-api/#useobserveeffect).

```jsx
import { event } from "@legendapp/state"
import { useObserve, useObservable } from "@legendapp/state/react"
import { $React } from "@legendapp/state/react-web"


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>
      <$React.input $value={profile$.name} />
    </div>
  )
}
```

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

`useObserveEffect` is the same as [useObserve](https://legend.so/state/v3/react/react-api/#useobserve) except that it runs after the component is mounted.

### [useWhen, useWhenReady](https://legend.so/state/v3/react/react-api/#usewhen-usewhenready)

These are hook versions of [when](https://legend.so/state/v3/usage/reactivity#when).

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

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

The `useObservable` hook creates 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/v3/react/react-api/#reading-state).

As with normal observables you can create a [computed observable](https://legend.so/state/v3/usage/observable#computed-observables) by just using a function.

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

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

    const fullname$ = useObservable(() => `${state$.first.get()} ${state$.last.get()}`)

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

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

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

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

function reducer(state, action) {
    if (action.type === 'incremented_age') {
        return {
            age: state.age + 1
        }
    }
}
const Component = () => {
    // Create local observable state and a dispatch function
    const [age$, dispatch] = useObservableReducer(reducer, { age: 42 })

    // Re-render when age changes
    const age = useValue(age$.age)
}
```

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

Passing an observable object through Context gives you all the benfits of Context without the downsides, like any change to context normally re-renders all consumers.

Simply set an observable as a Context value and consume it from a child component as usual. The observable itself is a stable object so useContext will never cause a re-render - only observing contexts will be updated as usual.

```tsx
import { createContext, useContext } from "react"
import type { Observable } from "@legendapp/state"
import { Memo, observer, useObservable } from "@legendapp/state/react"

interface UserState {
    profile: {
        name: string;
    };
}

// Create a typed context. It can have a default value of undefined because
// the Provider will always be created with an Observable.
const StateContext = createContext<Observable<UserState>>(undefined as any);

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/v3/react/react-api/#miscellaneous-hooks)

### [useEffectOnce](https://legend.so/state/v3/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")
  }, [])
}
```

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

Using observable hooks we generally avoid the built-in hooks and dependency arrays, so we have `useMount` and `useUnmount` hooks for convenience, which are just `useEffectOnce` under the hood.

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

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

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

Like the `useMount` hook, `useUnmount` just uses `useEffectOnce` under the hood.

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

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

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

This returns `{ PauseProvider, isPaused$ }`. Set `isPaused$` to `true` to pause rendering from observable changes under `PauseProvider`, and set it to `false` to resume. This applies to everything within Legend-State like observer, useValue, $React, Memo, etc... But normal renders coming from React or other state is not affected.

This can be very useful to stop all updating when UI is not even visible, such as when a fullscreen modal is covering app UI or in inactivate tabs in React Native.

[View Markdown](https://legend.so/state/v3/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%2Fv3%2Freact%2Freact-api%0A%0AWhat+is+incorrect+or+missing%3F%0A%0AExpected+behavior+or+supporting+source%3A%0A)
