ReactJS 教程

ReactJS - 主页 ReactJS - 简介 ReactJS - 路线图 ReactJS - 安装 ReactJS - 功能 ReactJS - 优势和缺点 ReactJS - 架构 ReactJS - 创建 React 应用程序 ReactJS - JSX ReactJS - 组件 ReactJS - 嵌套组件 ReactJS - 使用组件 ReactJS - 集合组件 ReactJS - 样式 ReactJS - 属性 (props) ReactJS - 使用属性创建组件 ReactJS - props 验证 ReactJS - 构造函数 ReactJS - 组件生命周期 ReactJS - 事件管理 ReactJS - 创建事件感知组件 ReactJS - Expense Manager 事件 ReactJS - 状态管理 ReactJS - 状态管理 API ReactJS - 无状态组件 ReactJS - Hooks 进行状态管理 ReactJS - Hooks 的组件生命周期 ReactJS - 布局组件 ReactJS - 分页 ReactJS - Material UI ReactJS - Http 客户端编程 ReactJS - 表单编程 ReactJS - 受控组件 ReactJS - 非受控组件 ReactJS - Formik ReactJS - 条件渲染 ReactJS - 列表 ReactJS - Key 键 ReactJS - 路由 ReactJS - Redux ReactJS - 动画 ReactJS - Bootstrap ReactJS - Map ReactJS - 表格 ReactJS - 使用 Flux 管理状态 ReactJS - 测试 ReactJS - CLI 命令 ReactJS - 构建和部署 ReactJS - 示例

Hooks

ReactJS - Hooks 简介 ReactJS - 使用 useState ReactJS - 使用 useEffect ReactJS - 使用 useContext ReactJS - 使用 useRef ReactJS - 使用 useReducer ReactJS - 使用 useCallback ReactJS - 使用 useMemo ReactJS - 自定义 Hooks

ReactJS 高级

ReactJS - 可访问性 ReactJS - 代码拆分 ReactJS - 上下文 ReactJS - 错误边界 ReactJS - 转发 Refs ReactJS - 片段 ReactJS - 高阶组件 ReactJS - 与其他库集成 ReactJS - 优化性能 ReactJS - Profiler API ReactJS - Portals ReactJS - 不使用 ES6 ECMAScript ReactJS - 不使用 JSX 的 React ReactJS - Reconciliation ReactJS - Refs 和 DOM ReactJS - 渲染道具 ReactJS - 静态类型检查 ReactJS - 严格模式 ReactJS - Web 组件

其他概念

ReactJS - 日期选择器 ReactJS - Helmet ReactJS - 内联样式 ReactJS - PropTypes ReactJS - BrowserRouter ReactJS - DOM ReactJS - 轮播 ReactJS - 图标 ReactJS - 表单组件 ReactJS - 参考 API

ReactJS 有用资源

ReactJS - 快速指南 ReactJS - 备忘录 Axios - 备忘录 ReactJS - 有用资源 ReactJS - 讨论


ReactJS - use Hook

正如我们在 React 中所知,"hook"是一种特殊函数,它允许我们将状态和其他 React 功能添加到我们的功能组件中。因此,"use"是一个 React Hook,它读取资源的值,例如 Promise 或上下文。与所有其他 React Hook 不同,use 可以在循环和条件表达式(如 if)中调用。与所有其他 React Hook 一样,调用 use 的函数必须是组件或 Hook。

use hook 的基本语法

const data = use(asset);

参数

asset − 它是我们要从中读取值的数据源。因此这可以是 Promise 或上下文。

返回值

此 Hook 将返回从资产读取的值,类似于返回 Promise 或上下文的解析值的方式。

"use"Hook 的用法

import { use } from 'react';
function TheComponent ({ thePromise }) {
   const msg = use(thePromise);
   const data = use(DataContext);
   // ...

带有 Promise 的'use'Hooks(钩子)

因此,通过使用带有'use'Hooks(钩子)的 Promise,我们可以将数据从服务器传输到客户端。通过将 Promise 作为从服务器组件到客户端组件的 prop,可以将数据从服务器发送到客户端。

import { Data } from './data.js';

export default function App() {
   const dataPromise = fetchData();
   return (
      <Suspense fallback={<p>waiting for the data...</p>}>
         <Message dataPromise={dataPromise} />
      </Suspense>
   );
}

然后,客户端组件将作为 prop 给出的 Promise 传递给 use Hook。这使客户端组件能够从服务器组件首次生成的 Promise 中读取值。

data.js

'use client';

import { use } from 'react';

export function Data({ dataPromise }) {
   const dataContent = use(dataPromise);
   return <h4>Here is the data: {dataContent}</h4>;
}

由于 Data 被包裹在 Suspense 中,因此回退会一直持续到 Promise 被解析。当 Promise 被解析时,Hook 会读取值,Data 组件将取代 Suspense 回退。

完整代码

Data.js

"use client";

import { use, Suspense } from "react";

function Data({ dataPromise }) {
   const dataContent = use(dataPromise);
   return <h4>Yup!!! Here is the Data: {dataContent}</h4>;
}

export function DataContainer({ dataPromise }) {
   return (
      <Suspense fallback={<p>⌛ Downloading Data...</p>}>
         <Data dataPromise={dataPromise} />
      </Suspense>
   );
}

App.js

import { useState } from "react";
import { DataContainer } from "./data.js";

function fetchData() {
   return new Promise((resolve) => setTimeout(resolve, 2000, "😃"));
}

export default function App() {
   const [dataPromise, setDataPromise] = useState(null);
   const [show, setShow] = useState(false);
   function download() {
      setDataPromise(fetchData());
      setShow(true);
   }
   
   if (show) {
      return <DataContainer dataPromise={dataPromise} />;
   } else {
      return <button onClick={download}>Download Your Data</button>;
   }
}

输出

dowloading data

如何处理被拒绝的 Promise

有时传递给"use"Hooks(钩子)的 Promise 可能会被拒绝。因此,我们可以处理这些被拒绝的 Promise,使用错误边界向用户显示错误,或者通过使用 Promise.catch 提供不同的值。

使用错误边界向用户显示错误

假设我们想在 Promise 被拒绝时向用户显示错误,因此我们可以使用错误边界。为此,我们可以在调用"use"Hooks(钩子)的组件周围放置一个错误边界。如果提供给 use 的 Promise 被拒绝,则将显示错误边界的后备。

示例

ItemListContainer.js

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

export function ItemListContainer({ itemListPromise }) {
   return (
      <ErrorBoundary fallback={<p>⚠ Something went wrong</p>}>
         <Suspense fallback={<p>⌛ Loading items...</p>}>
            <ItemList itemListPromise={itemListPromise} />
         </Suspense>
      </ErrorBoundary>
   );
}

function ItemList({ itemListPromise }) {
   const items = use(itemListPromise);
   return (
   <div>
      <h2>Item List:</h2>
      <ul>
         {items.map((item, index) => (
         <li key={index}>{item}</li>
         ))}
      </ul>
   </div>
   );
}

App.js

import { useState } from "react";
import { ItemListContainer } from "./ItemListContainer";

function fetchItems() {
   return new Promise((resolve) =>
      setTimeout(() => resolve(["Item 1", "Item 2", "Item 3"]), 1000)
   );
}

function App() {
   const [itemListPromise, setItemListPromise] = useState(null);
   const [show, setShow] = useState(false);
   
   function loadItems() {
      setItemListPromise(fetchItems());
      setShow(true);
   }
   
   if (show) {
      return <ItemListContainer itemListPromise={itemListPromise} />;
   } else {
      return <button onClick={loadItems}>Load Items</button>;
   }
}

export default App;

输出

loading items

使用 Promise.catch 提供备用值

如果提供的 Promise 被拒绝,我们可以使用 catch 方法提供备用值。

import { Data } from './data.js';

export default function App() {
   const dataPromise = new Promise((resolve, reject) => {
      reject();
   }).catch(() => {
      return "No data found.";
   });
   
   return (
      <Suspense fallback={<p>waiting for the data...</p>}>
         <Data dataPromise={dataPromise} />
      </Suspense>
   );
}

带有 Context 的"use"Hooks(钩子)

让我们看另一个"use"Hooks(钩子)的例子。所以我们将在 React − 中使用带有上下文的"use"函数

在这个例子中,我们将有一个用于管理主题的上下文;它可以是浅色或深色。然后我们将有一个名为 MyUseHookApp 的主应用程序组件。它是提供"浅色"主题的顶级组件,并将呈现表单组件。然后我们将创建一个名为 MyForm 的表单组件,该组件将呈现一个面板和三个按钮。之后,面板组件被命名为 MyPanel。它将根据上下文显示具有主题的内容。而 MyButton 组件则根据上下文显示一个具有主题的按钮。

这里所有组件都使用"use"Hooks(钩子)从上下文访问主题,并允许它们根据所选主题设置元素的样式。

示例

import { use, createContext } from 'react';

// 为主题创建上下文
const ThemeContext = createContext(null);

// 主应用程序组件。
export default function MyUseHookApp() {
   return (
      // light theme to all components
      <ThemeContext.Provider value="light">
         <MyForm />
      </ThemeContext.Provider>
   )
}

// 表单组件
function MyForm() {
   return (
      <MyPanel title="Welcome To My App">
         <MyButton show={true}>Join Here</MyButton>
         <MyButton show={true}>Begin</MyButton>
         <MyButton show={false}>Settings</MyButton>
      </MyPanel>
   );
}

// 面板组件用于显示带有主题的内容
function MyPanel({ title, children }) {
   const theme = use(ThemeContext);
   
   // 应用主题
   const className = 'panel-' + theme;
   
   return (
      <section className={className}>
         <h1>{title}</h1>
         {children}
      </section>
   )
}

// 按钮组件
function MyButton({ show, children }) {
   if (show) {
      const theme = use(ThemeContext);
      
      // 将主题应用到组件。
      const className = 'button-' + theme;
      
      return (
         <button className={className}>
            {children}
         </button>
      );
   }
   
   // If 'show' is false, return nothing.
   return false;
}

输出

welcome my app

缺点

与 useContext 一样,use(context) 会定期查找调用组件上方最近的上下文提供程序。它会查找并忽略调用 use(context) 的组件中的上下文提供程序。

限制

  • 我们应该在组件或Hooks(钩子)中使用"use"Hooks(钩子)。

  • 当我们在服务器上时,我们应该始终使用"async"和"await"来很好地获取数据。

  • 如果我们需要承诺,请在服务器上做出承诺,因为它们保持稳定,但在客户端,它们可能会发生很大变化。

这一切都是为了让我们的网页工作得更好、更高效。

reactjs_reference_api.html