在上一章中,我们学习了如何使用 Hook 请求资源。我们首先使用 State/Reducer 和 Effect Hook 实现了请求资源。然后,我们了解了 axios
和 react-request-hook
库。
在本章中,我们将创建多个页面并在应用程序中实现路由。路由在几乎所有应用程序中都很重要。为了实现路由,我们将学习如何使用 Navi 库,这是一个基于 Hook 的导航系统。最后,我们还将学习动态链接,以及如何使用 Hooks 访问路由信息。
本章将介绍以下主题:
- 创建多个页面
- 实现路由
- 使用路由 Hook
技术要求
应该已经安装了相当新版本的 Node.js(vl1.l2.0 或更高版本)。Node.js 的 npm
包管理器也需要安装。
本章的代码可以在 GitHub 存储库中找到:https://github.com/PacktPublishing/Learn-React-Hooks/tree/master/Chapter07。
观看以下视频,了解代码的实际应用:
请注意,强烈建议您自己编写代码。不要简单地运行已提供的代码示例。重要的是你自己编写代码,以便能够正确学习和理解。但是,如果遇到任何问题,始终可以参考代码示例。
现在,让我们从本章开始。
创建多个页面
目前,我们的博客应用程序是一个所谓的单页应用程序。但是,大多数较大的应用程序都包含多个页面。在博客应用程序中,我们至少希望每篇博客文章都有一个单独的页面。
在设置路由之前,我们需要创建要显示的各种页面。在我们的博客应用程序中,我们将定义以下页面:
- 主页,将显示所有文章的列表
- 一篇文章页面,将显示单篇文章
所有页面都将显示一个 HeaderBar
,它显示 Header
、UserBar
、ChangeTheme
和 CreatePost
组件。我们现在将首先为 HeaderBar
创建一个组件。之后,我们将实现页面组件。
创建 HeaderBar 组件
首先,我们将 App
组件的一些内容重构为 HeaderBar
组件。 HeaderBar
组件将包含我们希望在每个页面上显示的所有内容:Header
、UserBar
、ChangeTheme
和 CreatePost
组件。
让我们开始创建 HeaderBar
组件:
- 创建一个新文件夹:
src/pages/
。 - 创建一个新文件
src/pages/HeaderBar.js
,导入React
(使用useContext
Hook),并在那里定义组件。它将接受setTheme
函数作为 prop:
import React, { useContext } from 'react'
export default function HeaderBar({ setTheme }) {
return (
<div>
</div>
)
}
- 现在,从
src/App.js
组件中剪切以下代码,并将其插入HeaderBar
组件的<div>
标签之间:
<Header text="React Hooks Blog" />
<ChangeTheme theme={theme} setTheme={setTheme} />
<React.Suspense fallback={"Loading..."}>
<UserBar />
</React.Suspense>
{ user && <CreatePost /> }
- 另外,从
src/App.js
中剪切以下导入语句(并调整路径),并将它们在导入 React 语句之后,插入src/pages/HeaderBar.js
文件的开头:
import CreatePost from '../post/CreatePost'
import UserBar from '../user/UserBar'
import Header from '../Header'
import ChangeTheme from '../ChangeTheme'
- 此外,导入
ThemeContex
和StateContext
:
import { ThemeContext, StateContext } from '../contexts'
- 然后,为
theme
和state
定义两个 Context Hook,并将user
变量从src/pages/HeaderBar.js
中的state
对象中解构,因为我们需要它进行条件检查以确定我们是否应该渲染CreatePost
组件:
export default function HeaderBar({ setTheme }) {
const theme = useContext(ThemeContext)
const { state } = useContext(StateContext)
const { user } = state
return (
- 现在,我们在
src/App.js
中导入HeaderBar
组件:
import HeaderBar from './pages/HeaderBar'
- 最后,我们在
src/App.js
中渲染HeaderBar
组件:
<div style={{ padding: 8 }}>
<HeaderBar setTheme={setTheme} />
<hr />
现在,我们有一个单独的 HeaderBar
组件,它将显示在所有页面上。接下来,我们继续创建 HomePage
组件。
创建 HomePage 组件
现在,我们将从 PostList
组件和与文章相关的 Resource Hook。同样,我们将重构 src/App.js
,以便创建一个新组件。
让我们开始创建 HomePage
组件:
- 创建一个新文件
src/pages/HomePage.js
,导入React
和useEffect
、useContext
Hook,并在那里定义组件。我们还定义了一个 Context Hook,并解构出state
对象和dispatch
函数:
import React, { useEffect, useContext } from 'react'
import { StateContext } from '../contexts'
export default function HomePage() {
const { state, dispatch } = useContext(StateContext)
const { error } = state
return (
<div>
</div>
)
}
- 然后,从
src/App.js
中剪切以下导入语句(并调整路径),并将它们添加到src/pages/HomePage.js
中的import React from 'react'
语句之后:
import { useResource } from 'react-request-hook'
import PostList from '../post/PostList'
- 接下来,从
src/App.js
中剪切以下 Hook 定义,并将它们插入HomePage
函数的return
语句之前:
const [posts, getPosts] = useResource(() => ({
url: '/posts',
method: 'get'
}))
useEffect(getPosts, [])
useEffect(() => {
if (posts && posts.error) {
dispatch({ type: 'POSTS_ERROR' })
}
if (posts && posts.data) {
dispatch({ type: 'FETCH_POSTS', posts: posts.data.reverse() })
}
}, [posts])
- 现在,从
src/App.js
中剪切以下渲染代码,并将其插入src/pages/HomePage.js
的<div>
标签之间:
{error && <b>{error}</b>}
<PostList />
- 然后,在
src/App.js
中导入HomePage
组件:
import HomePage from './pages/HomePage'
- 最后,在
<hr />
标记下渲染HomePage
组件:
<hr />
<HomePage />
现在,我们已经成功地将当前代码重构为 HomePage
组件。接下来,我们继续创建 PostPage
组件。
创建 PostPage 组件
我们现在将定义一个新的页面组件,其中我们只会从我们的 API 中获取单篇文章并显示它。
现在让我们开始创建 PostPage
组件:
- 创建一个新的
src/pages/PostPage.js
文件。 - 导入
React
、useEffect
和useResource
Hook 以及Post
组件:
import React, { useEffect } from 'react'
import { useResource } from 'react-request-hook'
import Post from '../post/Post'
- 现在,定义
PostPage
组件,它将接受文章id
作为prop:
export default function PostPage ({ id }) {
- 在这里,我们定义了一个 Resource Hook,它将获取相应的
post
对象。我们将id
作为依赖项传递给 Effect Hook,以便在id
更改时重新获取资源:
const [post, getPost] = useResource(() => ({
url: '/posts/${id}' ,
method: 'get'
}))
useEffect(getPost, [id])
- 最后,我们渲染
Post
组件:
return (
<div>
{(post && post.data)
? <Post {...post.data} />
: 'Loading...'
}
<hr />
</div>
)
}
我们现在还有一个单独的页面用于单篇文章。
测试 PostPage
为了测试新页面,我们将 src/App.js
中的 HomePage
组件替换为 PostPage
组件,如下所示:
- 在
src/App.js
中导入PostPage
组件:
import PostPage from './pages/PostPage'
- 现在,将
HomePage
组件替换为PostPage
组件:
<PostPage id={'react-hooks'} />
正如我们所看到的,现在只有显示一篇文章,即“the React Hooks post”。
示例代码
示例代码可以在 Chapter07/chapter7_1
文件夹中找到。
只需运行 npm install
即可安装所有依赖项,运行 npm start
启动应用程序,然后在您的浏览器中访问 http://localhost:3000
(如果它没有自动打开)。
(节选)
评论 (0)