Home » Use(): React’s New Experimental Hook

Use(): React’s New Experimental Hook

use hook

A new hook called “use” is generating a lot of buzz among the React team and the JavaScript community. People are discussing how to implement it and are exploring its potential for future use.

What is use() hook?

  • Use() hook is a new experimental feature that allows you to write async code in React using promises.
  • It operates similarly to ‘await’, but with some important differences.
  • It enables you to write asynchronous code in a declarative manner without using useEffect or suspense.
  • It also has some special properties such as being exempt from the rules of hooks and requiring caching for data fetching.

How does use() hook work?

  • Use() hook takes a promise as an argument and returns its resolved value when it’s ready.
  • If the promise is not ready yet (pending), it throws an error which triggers suspense fallbacks.
  • If the promise is rejected (error), it throws an error which triggers error boundaries.
  • Use() hook also caches the resolved value of each promise so that subsequent renders can reuse it without refetching data.

What are the benefits of use() hook?

  • Use() hook simplifies async code by eliminating useEffect boilerplate and suspense configuration.
  • Use() hook makes async code more readable by avoiding nested callbacks or then chains.
  • Use() hook enables conditional rendering based on promise status without using state variables or ternary operators.

What are the drawbacks of use() hook?

  • Use() hook is still experimental and not officially supported by React yet.
  • Use() hook requires caching for data fetching which might introduce memory leaks or stale data issues if not handled properly.
  • Use() hook breaks some conventions such as rules of hooks which might confuse some developers or tools.

How to use in your projects?

1. Setup

  • I’m using a Vite + React boilerplate project with JavaScript.
    Run in Terminal: npm create vite@latest
  • To use use() hook in your projects, you need to install react experimental version.
    Run in Terminal: npm install react@experimental react-dom@experimental or: yarn add react@experimental react-dom@experimental
  • To Start App use cmd: npm run dev

package.json file:

{
  "name": "usehook",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^0.0.0-experimental-bfb9cbd8c-20230223",
    "react-dom": "^0.0.0-experimental-bfb9cbd8c-20230223"
  },
  "devDependencies": {
    "@types/react": "^18.0.27",
    "@types/react-dom": "^18.0.10",
    "@vitejs/plugin-react": "^3.1.0",
    "vite": "^4.1.0"
  }
}

2. use Hook Implementation

How do we fetch data nowadays?

//App.js

import Post from './post';
import './App.css';
function App() {
	const url = 'https://jsonplaceholder.typicode.com/posts/1';
	return (
		<>
			<Post url={url} />
		</>
	);
}
export default App;

//Post.jsx

import { useEffect, useState } from 'react';

const Post = ({ url }) => {
	const [isLoading, setIsLoading] = useState(true);
	const [isError, setIsError] = useState(false);
	const [post, setPost] = useState([]);

	useEffect(() => {
		setIsError(false);
		setIsLoading(true);
		setPost([]);

		fetch(url)
			.then((res) => res.json())
			.then(setPost)
			.catch(() => setIsError(true))
			.finally(() => setIsLoading(false));
	}, [url]);

	if (isLoading) return <div>Loading...</div>;
	if (isError) return <div>{isError}</div>;
	return <>{post.title}</>;
};

export default Post;

This code creates a simple React application that fetches a single post object from a JSON API endpoint and displays its title on the screen.

The App component renders the Post component and passes the URL of the API endpoint as a prop.

The Post component is responsible for fetching the post data from the API endpoint. It uses the useEffect hook to make the API call and update the component state accordingly. While the data is being fetched, the component displays a “Loading…” message. If there is an error in fetching the data, an error message is displayed. Once the data is successfully retrieved, the component displays the post title on the screen.

Overall, this code demonstrates how to fetch data from an API endpoint and use it to update the state of a React component. It also shows how to handle loading and error states while fetching data.

Dealing with asynchronous tasks in React, like promises, can be a pain. But, using use hook can simplify things. By importing just this, we can eliminate the need for useState and useEffect and make our code more efficient.

What the new use hook looks like?

//Post.jsx

import { use } from 'react';

function Post({ url }) {
	const post = use(fetch(url).then((res) => res.json()));
	return <div>{post.title}</div>;
}

export default Post;

In this example you seen we essentially reduced this component to two simple line.
Other good thing is if you are trying to console.log(post) you will see that post is never undefined.

3. Loading State (Suspense) and Error Handling

We need to handle the loading and the error state and we actually need to do that inside of our app component.

React suspense is doing asynchronous thing in react so we can take this and wrap our child component and wrap again with ErrorBoundary component to handle errors that may occur during data fetching or rendering.

Here is an example of how you can use Suspense and Error Handling with React Hooks:

//App.js

import { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';
import Post from './post';
import './App.css';

function App() {
	const url = 'https://jsonplaceholder.typicode.com/posts/1';
	return (
		<ErrorBoundary fallback={<div>Error</div>}>
			<Suspense fallback={<div>loading...</div>}>
				<Post url={url} />
			</Suspense>
		</ErrorBoundary>
	);
}

export default App;

ErrorBoundary.jsx file:

//ErrorBoundary.jsx 

import React from 'react';

class ErrorBoundary extends React.Component {
	constructor(props) {
		super(props);
		this.state = { hasError: false };
	}

	static getDerivedStateFromError(error) {
		// Update state so the next render will show the fallback UI.
		return { hasError: true, error };
	}

	render() {
		if (this.state.hasError) {
			// You can render any custom fallback UI
			return this.props.fallback;
		}

		return this.props.children;
	}
}

export default ErrorBoundary;

4. use Hook Rules

An interesting aspect of this hook is that it executes prior to component rendering, enabling the inclusion of conditional statements preceding its definition, as demonstrated below:

//Post.jsx

import { use } from 'react';

function Post({ url, shouldFetch }) {
	let post = 'default title';
	if (shouldFetch) {
		post = use(fetch(url));
	}
	return <div>{post.title}</div>;
}

export default Post;

//App.js

import { Suspense } from 'react';
import ErrorBoundary from './ErrorBoundary';
import Post from './post';
import './App.css';

function App() {
	const url = 'https://jsonplaceholder.typicode.com/posts/1';
	return (
		<ErrorBoundary fallback={<div>Error</div>}>
			<Suspense fallback={<div>loading...</div>}>
				<Post url={url} shouldFetch />
			</Suspense>
		</ErrorBoundary>
	);
}

export default App;

In this example, I’ve passed the ‘shouldFetch‘ flag to the ‘Post’ component and I only want to execute the fetch if ‘shouldFetch‘ is true. This is typically a significant issue in React when working with hooks, as they cannot be wrapped inside if statements or similar constructs.

However, the use hook function behaves differently. All the usual rules about hooks and conditional statements are thrown out the window, as this can be placed practically anywhere, including inside a for loop or if statement.


Conclusion

Both the React team and community are actively striving to develop more effective approaches for data fetching and server components. 🚀

The use of the latest React hook, “use,” is remarkably distinct and fascinating as it deviates from the conventional hook norms. Unlike any other hook, it can be utilized within loops and conditional statements. 😲

This also removes the need for many useEffect statements which I am a huge fan of. 👍

Love to hear from you! Share your thoughts and suggestions in the comments below.


For more tips and best practices on React development, check out my blog post on react useEffect.

Check it out here: Mastering useEffect in React

2 thoughts on “Use(): React’s New Experimental Hook

  1. This design is steller! You obviously know
    how to keep a reader amused. Between your wit and your videos, I was almost moved to start my own blog (well,
    almost…HaHa!) Excellent job. I really loved
    what you had to say, and more than that, how you presented
    it. Too cool! I saw similar here: najlepszy sklep
    and also here: najlepszy sklep

Leave a Reply

Your email address will not be published. Required fields are marked *