# Source: https://developers.raycast.com/misc/migration/v1.37.0.md

# v1.37.0

This version now depends on [React 18](https://reactjs.org/blog/2022/03/29/react-v18.html). As part of this change, the `@raycast/api` package now has strong dependencies on `@types/react` and `@types/node` so those 2 packages shall be removed from your extension's devDependencies (this will be done automatically by `npx ray migrate`).

There are no breaking changes introduced in React 18 so all your extensions will still work properly. However, there are some breaking changes in `@types/react` so you might have to do some minor tweaks if you use TypeScript.

We had a [pass](https://github.com/raycast/extensions/compare/f/fix-ts) through all the extensions on the public repo. Notably, if you are using `raycast-toolkit` or `swr`, you will have to update them to their latest version.

## React Suspense

{% hint style="info" %}
Suspense is an advanced feature of React. You do not need to use or understand it to build Raycast extensions (or any React application). We are not going to teach Suspense here but we will highlight how you can work with it in Raycast.
{% endhint %}

You can now use Suspense in Raycast. We provide a top-level `Suspense` fallback so you don't have to. This fallback simply turns on the `isLoading` on the top level view.

```jsx
import { List, Toast, showToast, ActionPanel, Action, Icon, popToRoot } from "@raycast/api";
import { useState, useCallback } from "react";
import * as twitter from "./oauth/twitter";

// a hook that suspends until a promise is resolved
import { usePromise } from "./suspense-use-promise";

const promise = async (search: string) => {
  try {
    await twitter.authorize();
    return await twitter.fetchItems(search);
  } catch (error) {
    console.error(error);
    showToast({ style: Toast.Style.Failure, title: String(error) });
    return [];
  }
};

export default function Command() {
  const [search, setSearch] = useState("");

  const items = usePromise(promise, [search]);

  const logout = useCallback(() => {
    twitter.logout();
    popToRoot();
  }, []);

  const actionPanel = (
    <ActionPanel>
      <Action title="Logout" onAction={logout} />
    </ActionPanel>
  );

  // no need to set the `isLoading` prop, Raycast will set it automatically
  // until the React application isn't suspended anymore
  return (
    <List onSearchTextChange={setSearch} throttle>
      {items.map((item) => {
        return (
          <List.Item key={item.id} id={item.id} icon={Icon.TextDocument} title={item.title} actions={actionPanel} />
        );
      })}
    </List>
  );
}
```