Comment on page
v1.37.0
This version now depends on React 18. 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 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.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.
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.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>
);
}
Last modified 1yr ago