组件层次结构以及如何获取异步数据
介绍
React 使我们可以轻松地在视图中显示数据。我们可以遵循不同的组件层次结构来显示数据。在本指南中,我们将了解其中一些组件层次结构,并学习如何获取异步数据、在数据加载完成之前显示加载指示器以增强用户体验,以及在用户滚动到底部时加载更多数据。
异步数据获取
首先,我们将数据提取到我们的应用程序中。在 React 中,有两种方法可以获取异步数据:fetch API 和 Axios 库。
浏览器获取 API
fetch ()方法在浏览器中是原生可用的,就像XMLHttpRequest (XHR)一样。这两者之间的显著区别在于fetch API 使用Promises ,与XHR相比,它更容易使用,语法也更简洁。
一个基本的fetch()请求如下:
const URL = "www.example.com/posts";
fetch(URL)
.then(function(response) {
// parse the response into suitable format
// response.text()
response.json();
})
.then(function(data) {
// actual data is passed here
console.log(data);
});
fetch ()方法返回一个Stream对象,这意味着我们可以将流解析为json、text或blob。 要将流解析为json,我们可以使用json()方法,该方法返回一个Promise,其中包含成功时的实际数据。
我们可以进一步简化语法并避免使用 ES6 async-await语法的回调。
async function getPosts() {
const URL = "www.example.com/posts";
const response = await fetch(URL);
const data = await response.json();
console.log(data);
return data;
}
默认情况下,fetch()会向 URL 发出 GET 请求。您可以在配置对象中指定方法,并将其作为第二个参数传入。
async function addPost(postData) {
const URL = "www.example.com/posts";
const response = await fetch(URL, { method: "POST", data: postData });
const data = await response.json();
console.log(data);
return data;
}
Axios JavaScript 库
Axios 是一个流行的 Javascript 库,用于执行 HTTP 请求,类似于fetch API。两者之间的主要区别在于 Axios 在内部自动转换为 JSON,并减少了在fetch中获取实际数据的两步过程。
使用 Axios 的基本 HTTP GET 请求可以按如下方式完成:
function getPosts() {
const URL = "www.example.com/posts";
axios.get(URL).then(response => console.log(response.data));
}
// using async-await
async function getPosts() {
const URL = "www.example.com/posts";
const { data } = await axios.get(URL);
return data;
}
有关 Axios 的更多信息,请参阅本指南。
请注意,为了简洁起见,我没有在 try-catch 块中编写异步调用。处理网络请求时,必须将代码封装在 try-catch 中,因为有时请求可能会因网络错误或服务器问题而失败。
组件层次结构
现在我们知道了如何在 React 中获取异步数据,让我们看一下如何在组件中显示数据以及组件的一些层次结构。
单组分
在单组件层次结构中,数据在同一组件中获取和显示。组件可以在使用componentDidMount()生命周期方法安装后,通过单击按钮获取数据,或者定期获取数据以与服务器保持同步。
让我们看看如何使用componentDidMount()方法获取数据。
class Posts extends Component {
state = { posts: [] };
async componentDidMount() {
const posts = await getPosts();
this.setState({ posts });
}
render() {
return (
<div class='posts-container'>
{this.state.posts.map(post => (
<div class={`post post-id-${post.id}`}>
<div class='post-image'>
<img src={post.imageUrl}>
</div>
<div class='post-title'>
<h4> {post.title} </h4>
</div>
</div>
))}
</div>
)
}
}
由于getPosts()是一个异步函数,它将返回一个 Promise,因此我使用了 async-await 语法。在下一行中,我更新了状态以保存帖子。在render()方法中,我使用了Array.map()方法来显示每个帖子。
现在,让我们使用最新的 React Hooks API 执行相同操作。React Hooks 允许我们在功能组件内部拥有状态。
import React, { useState } from "react";
const Posts = () => {
const [posts, setPosts] = useState([]);
// return
};
useState ()方法声明一个状态变量和一个可用于更改状态变量的方法。我们将初始状态传递给 useState ()方法,在我们的例子中是一个空数组。它返回一个由两个值组成的数组:初始状态和修改它的方法。在我们的示例中,这些值分别存储在posts和setPosts中。
为了执行异步数据获取,我们使用useEffect钩子函数。
import React, { useState, useEffect } from "react";
const Posts = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
(async () => {
const fetchedPosts = await getPosts();
setPosts(fetchedPosts);
})();
}, []);
return (
<div class='posts-container'>
{posts.map(post => (
<div class={`post post-id-${post.id}`}>
<div class='post-image'>
<img src={post.imageUrl}>
</div>
<div class='post-title'>
<h4> {post.title} </h4>
</div>
</div>
))}
</div>
)
};
useEffect ()函数接受一个函数作为第一个参数,第二个参数是该函数所依赖的所有变量的数组。在我们的例子中,将一个空数组传递给钩子很重要;否则,该函数将在每次组件更新时执行。这是一个讨厌的错误,我们应该避免它。你一定注意到我将 async-await 块包装在一个自调用函数中。这是因为 useEffect 函数不能返回 Promise 对象,如果你尝试这样做,它会抛出一个错误。
高阶组件(HOC)
在高阶组件层次结构中,数据在父组件中获取,并作为 props 传递给子组件。嵌套在子组件中的其他组件可以接收获取数据的不同部分。
其理念是将数据获取逻辑与视图分离,将更多精力放在处理或向用户呈现数据上。这里更加强调 SOC,即关注点分离。
因此在我们的父组件中,我们将有以下代码。
const Posts = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
(async () => {
const fetchedPosts = await getPosts();
setPosts(fetchedPosts);
})();
}, []);
return (
<div class="posts-container">
{this.state.posts.map(post => (
<Post post={post} />
))}
</div>
);
};
在我们的子组件中,我们将编写模板来显示帖子:
const Post = {post} => (
<div class={`post post-id-${post.id}`}>
<div class='post-image'>
<img src={post.imageUrl}>
</div>
<div class='post-title'>
<h4> {post.title} </h4>
</div>
</div>
)
如您所见,与单个组件层次结构相比,父组件现在更轻巧且更易读。这样,我们可以将演示组件与容器组件分开。演示组件更倾向于生成标记以输出数据,而容器组件则负责从后端 API 获取和处理数据。
渲染 Props 组件
在渲染 props 组件层次结构中,组件接受一个返回 React 元素作为 prop 的函数,并在其render()函数中调用它,而不是实现其渲染逻辑。
考虑这个例子。假设除了帖子之外,您还有一个显示用户数据的组件。在这种情况下,您可能希望封装并重用两个组件之间的代码。为此,我们将创建一个<FetchComponent />,它将 URL 作为 prop 以及渲染函数。
// for displaying posts
<FetchComponent url="http://example.com/posts" render={post => <Post post={post} />} />
// for displaying users
<FetchComponent url="http://example.com/users" render={user => <User user={user} />} />
现在,让我们编写<font styl
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~