使用 Hooks 获取数据并更新状态
使用 Hooks 获取数据并更新状态
前一个指南介绍了如何从 REST API 获取数据以及如何使用结果重新渲染 React 组件。该指南详细说明了如何使用每个 React 类组件提供的componentDidMount()生命周期方法执行此操作。然而,许多组件并不是以类的形式编写的。很可能是因为现代浏览器尚未完全支持类,并且需要使用 Babel 或 TypeScript 将其转换为受支持的 JavaScript。如果不使用类而是使用普通函数声明来创建组件,则该组件称为函数组件。在 React 中,函数组件没有与类相同的内置生命周期方法。它们也没有自己的状态,因此你不能调用this.setState(...)。因此,你可能想知道如何获取数据并重新渲染组件。
介绍 Hooks
从 16.8 版开始,React 函数式组件实际上已经能够使用自己的状态和自己的生命周期方法。此功能得益于 React 的新Hooks。
钩子 (Hooks) 是以use...为前缀的函数,允许您从功能组件中挂钩到组件的生命周期功能。
有 10 个可用的内置钩子,但最常见的两个钩子是useState和useEffect。
使用状态
根据文档,useState钩子类似于类组件中的this.setState()调用,只是它不会将新旧状态合并在一起。 useState 钩子返回状态值和用于更新该状态的函数:
import React from 'react';
function BooksList () {
const [books, updateBooks] = React.useState([]);
}
上面的示例展示了如何使用 useState 钩子。它声明一个名为books 的状态变量,并用一个空数组初始化它。数组解构语法可能看起来很吓人,但它允许您命名状态变量和更新函数。该更新函数允许您像这样更新状态:
function BooksList () {
const [books, updateBooks] = React.useState([]);
const handleClick = () => {
// update the books state property by adding a new book
updateBooks([...books, { name: 'A new Book', id: '...'}]);
}
return (
<ul>
books.map(book => (
<li key={book.id}>{book.name}</li>
));
</ul>
);
}
当调用上述handleClick方法时,将使用新的书籍数组作为唯一参数来调用updateBooks更新程序函数。然后,将更新books属性,并且组件将使用books的新值重新呈现。
useEffect
当您必须在功能组件中执行副作用时,可以使用有用的useEffect钩子。
Effect Hook让你可以在函数组件中执行副作用
useEffect 钩子接受两个参数:一个函数和一个依赖项列表。如果函数或依赖项发生变化,则调用该函数。
function BooksList () {
const [books, updateBooks] = React.useState([]);
React.useEffect(function effectFunction() {
if (books) {
updateBooks([...books, { name: 'A new Book', id: '...'}]);
}
}, []); // This empty array represents an empty list of dependencies
...
}
上面的示例引入了具有空依赖项列表的 useEffect 钩子。因此,此钩子仅在组件初始化时运行。它不会在其他时间运行,因为它没有任何需要监视的依赖项。
使用空数组提供的功能几乎与类组件的componentDidMount()生命周期方法相同。
以下示例显示了如果在依赖项数组中提供了一个值会发生什么情况:
function BooksList () {
const [books, updateBooks] = React.useState([]);
const [counter, updateCounter] = React.useState(0);
React.useEffect(function effectFunction() {
if (books) {
updateBooks([...books, { name: 'A new Book', id: '...'}]);
}
}, [counter]);
const incrementCounter = () => {
updateCounter(counter + 1);
}
...
}
在这个例子中,effectFunction将在组件初始化时被调用,并且每次计数器变量改变时也会被调用。
使用useEffect钩子时,通常会将其与所有类组件生命周期方法进行比较。相反,您应该从您希望状态在某些变量发生变化后如何呈现的角度来考虑useEffect钩子。
关于useEffect钩子需要记住的一些规则:
- 您不能在条件内调用钩子;
- 必须按照完全相同的顺序调用 Hooks。将 useEffect 放在条件语句中可能会破坏该循环;
- 传递给钩子的函数不能是异步函数,因为异步函数隐式返回承诺,而 useEffect 函数要么不返回任何内容,要么返回清理函数。
整合起来
需要 useEffect 的一个常见用例是从服务器获取一些数据并使用其内容更新状态。您可以结合使用 useEffect 钩子和 useState 钩子来实现此行为。假设您想从 REST API 获取《哈利波特》书籍列表。获取后,您想在组件中显示无序列表的书名。它看起来像这样:
import React from 'react';
function BooksList () {
const [books, updateBooks] = React.useState([]);
React.useEffect(function effectFunction() {
fetch('https://the-fake-harry-potter-api.com/books')
.then(response => response.json())
.then(({ data: books }) => {
updateBooks(books);
});
}, []);
return (
<ul>
books.map(book => (
<li key={book.id}>{book.name}</li>
));
</ul>
);
}
上述钩子仅在组件初始化时运行。如果你更有可能在 useEffect 钩子中使用async/await ,它可能看起来像这样:
function BooksList () {
const [books, updateBooks] = React.useState([]);
React.useEffect(function effectFunction() {
async function fetchBooks() {
const response = await fetch('https://the-fake-harry-potter-api.com/books');
const json = await response.json();
updateBooks(json.data);
}
fetchBooks();
}, []);
return (
<ul>
books.map(book => (
<li key={book.id}>{book.name}</li>
));
</ul>
);
}
结论
引入 Hooks API 可为您的功能组件提供许多功能。useEffect钩子允许您处理副作用,例如日志记录、进行异步调用或在本地存储上设置值。useState钩子允许您为功能组件提供状态,这在以前是不可能的,除非您使用类组件。 后面的指南将介绍更多钩子功能,包括如何创建自己的自定义钩子。
如果您想了解如何使用类组件更新状态和重新渲染组件,请查看本指南。
了解更多
探索 Pluralsight 的这些 React 课程以继续学习:
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~