New Suspense Hooks for Meteor
Tags: webdev, javascript, react, showdev
Published: 2023-03-20 13:42:48




![New Suspense hooks for Meteor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l4t4sd7fqjh6bu453glu.png)



As we learned in the previous part of this series, why and how we could use [Suspense](https://dev.to/grubba/making-promises-suspendable-452f). This article will discuss and show how to use Meteor's newly added suspendable hooks.

With the changes coming to Meteor, especially with its fibers-free future, we decided to add to our hooks collection `react-meteor-data` a few hooks that can deal with those new async methods.

For starters, we need to address that `useFind` still works as it always did on the *client;*
it was implemented using synchronous functions, so it was safe from change. But important to note that if you are using the `useFind` hook on the server, for example, while using SSR, you will need to use the newly added `suspense/useFind` hook. This is important because now you cannot do a sync database search with the current implementation of `useFind` in the server, but with the newly added Suspense version, you can.

Before showing examples, we would like to show another made-suspendable hook: `useSubscribe` now. Instead of using an `isLoading` function to know when the subscription is ready, we made it use the Suspense API. Let's look at how it was before and how it will be:

```jsx

// before
// Tasks.jsx
function Tasks(){
	const [hideDone, setHideDone] = useState(false);
	const isLoading = useSubscribe("tasks");
	const filter = hideDone ? { done: { $ne: true }  } : {  };
	const tasks = useFind(
	    () => TasksCollection.find(filter, { sort: { createdAt: -1 } }),
	    [hideDone]
	);

	if (isLoading()) return <Loader />

	// render the tasks
}

// With suspense
// Tasks.jsx (have a Suspense wrapper outside with fallback={ <Loader /> }
function Tasks(){
	const [hideDone, setHideDone] = useState(false);
	useSubscribe("tasks");
	const filter = hideDone ? { done: { $ne: true }  } : {  };
	const tasks = useFind(
	    TasksCollection,
			[filter, { sort: { createdAt: -1 } }],
	    [hideDone]
	);

	// render the tasks
}
```

It looks and feels almost the same. We just moved the `isLoading` to the outside, and now we have a much more declarative code with a better Developer experience.

The changes regarding the `useFind` are how you build your function. Now you should pass the Collection, the arguments, and its dependencies.

## What about useTracker?

In this part, there will be a change to suspend when async. This is due to how Suspense works under the hood(a simple explanation: we need a way to track the promises when they are thrown, for a longer version, [check the previous article from this series](https://dev.to/grubba/making-promises-suspendable-452f) ). One of the things we will need to add one key to each useTracker instance.

```jsx
// before
// Tasks.jsx

function Tasks(){
	const isLoading = useSubscribe("tasks");
	const { username } = useTracker(() => Meteor.userAsync())
	const tasksByUser = useTracker(() => 
			 TasksCollection.find({username}, { sort: { createdAt: -1 } }).fetch()
	);

	if (isLoading()) return <Loader />

	// render the tasks
}

// With suspense
// Tasks.jsx (have a Suspense wrapper outside with fallback={ <Loader /> }
function Tasks(){
	useSubscribe("tasks");
	const { username } = useTracker("user",() => Meteor.userAsync()) 
	const tasksByUser = useTracker("tasksByUser", () =>
		 TasksCollection.find({username}, { sort: { createdAt: -1 } }).fetchAsync() // fetch will be async
	);

	// render the tasks
}

```

It seems more bloated due to the addition of strings, but now we do not need to think about loading states, and for some of them, the new react rendering engine improves our performance, and the reactivity is maintained between renders.

## Why are these changes so significant?

If, in your case, you only used `useFind` as before, without SSR and without using useTracker with async dependencies such as calling a fetch from a collection, then you may not need to update as these changes are just new API areas for solving the newly added functionalities that were added in Meteor 3.