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