likes
comments
collection
share

精读React hooks(十六):一个为代码优雅而生的hook——use

作者站长头像
站长
· 阅读数 70

截止发文日期,use 还是一个预发布的 hook,将来有可能会进行破坏性更新,所以不推荐在生产环境使用。但这不妨碍我们学习,万一过段时间 use 转正了呢?

use的使用

use 可以让你在函数组件中读取类似于 Promise 或 context 的资源的值。它的基础用法如下:

import { use } from 'react';

function MessageComponent({ messagePromise }) {
  const message = use(messagePromise);
  const theme = use(ThemeContext);
  // ...
}

use 函数的参数是你想要读取的资源,资源可以是 Promise 或 Context(在这个例子中是 messagePromiseThemeContext),并返回从资源中读取的值。

use解决的问题场景

在过去,React 开发者在处理类似于 Promise 或 Context 的资源时,通常需要将这些资源的值存储在 state 中,然后在组件中通过 props 或 state 来使用这些值。这种方法虽然可行,但是会增加代码的复杂性,并可能导致状态管理的困难。

use 这个 hook 解决了这个问题,因为它让你能够直接在组件中调用并获取这些资源的值,这样可以简化代码,使其更易于理解和维护。

想象一个场景,加入你正在开发一个博客应用,这个应用需要从 API 获取博客文章的内容,不用 use 的时候,你会这么做:

import { useState, useEffect } from 'react';

function BlogPostComponent({ postId }) {
  const [post, setPost] = useState(null);

  useEffect(() => {
    fetchPost(postId).then(data => setPost(data));
  }, [postId]);

  // ...
}

用上 use,就可以这么做:

import { use } from 'react';

function BlogPostComponent({ postId }) {
  const postPromise = fetchPost(postId);
  const post = use(postPromise);
  // ...
}

在功能上是一样的,但是用了 use 明显代码更优雅了。

use用于条件语句和循环中

其他 React hook 不同,use 可以在组件里的循环和条件语句中使用。例如:

  • 根据博客内容类别,读取不同 Promise
import { use } from 'react';

function ResourceComponent({ resourceType }) {
  let resource;

  if (resourceType === 'post') {
    const postPromise = fetchPost();
    resource = use(postPromise);
  } else if (resourceType === 'comment') {
    const commentPromise = fetchComment();
    resource = use(commentPromise);
  }

  // ...
}
  • 在组件里读取一个包含多个资源的数组
import { use } from 'react';

function ResourceListComponent({ resourcePromises }) {
  const resources = resourcePromises.map(resourcePromise => use(resourcePromise));

  // ...
}

将数据从服务器流式传递给客户端

以下是一个示例,展示了如何在服务器组件中创建一个Promise,并将其作为prop传递给客户端组件:

// 服务器组件
function ServerComponent({ postId }) {
  const postPromise = fetchPost(postId);
  return <ClientComponent postPromise={postPromise} />;
}

// 客户端组件
import { use } from 'react';

function ClientComponent({ postPromise }) {
  const post = use(postPromise);
  // ...
}

ClientComponent 中,我们使用 use 这个Hook来读取 **ServerComponent** 传过来的 Promise。

如果不用 use,我们也可以在 ServerComponentawait 来完成请求,然后把请求结果通过prop传给 ClientComponent,不过 await 会在执行完成前阻塞服务端组件的渲染,而使用 use 不会影响服务端组件的渲染。

处理 rejected Promise

有 Promise 的地方就要提供处理 rejected Promise 的方法。当你使用use的时候,有以下两种方法可以处理 rejected Promise:

1、ErrorBoundary

我们可以用 ErrorBoundary 包裹可能出错的组件,如果传递给 **use** 的 Promise rejected 了,将显示 ErrorBoundary 的 fallback:

"use client";
import { use, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function BlogPostComponent() {
  const postPromise = fetchPost(postId);

  return (
    <ErrorBoundary fallback={<p>⚠️Something went wrong</p>}>
      <Suspense fallback={<p>⌛Loading...</p>}>
        <BlogPostTitle messagePromise={messagePromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function BlogPostTitle({ postPromise }) {
  const post = use(postPromise);
  // ...

	return <p>Here is the title: {post.title}</p>;
}

2、Promise.catch

如果你不想用 ,但又想在 rejected 时有值填充,可以使用 Promise 的 catch 方法。

"use client";
import { use, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function BlogPostComponent() {
const postPromise = fetchPost(postId).catch((error) => {
    console.error('Failed to fetch post:', error);
    return 'https://weijunext.com'; // 返回一个默认值
  });

  return (
    <Suspense fallback={<p>⌛Loading...</p>}>
      <BlogPostTitle messagePromise={messagePromise} />
    </Suspense>
  );
}

结语

use 还只是一个实验性,等它正式转正之后,想必也会成为社区里宣传 React 代码优化之道的一项指南。

专栏结语

专栏资源

专栏演示站:👉 React Hooks Demos

专栏源码:👉 Github

专栏文章列表:

转载自:https://juejin.cn/post/7280975586902163468
评论
请登录