第 7 章 使用 Hook 进行路由

第 7 章 使用 Hook 进行路由

Flying
2021-03-10 / 0 评论 / 190 阅读 / 正在检测是否收录...

在上一章中,我们学习了如何使用 Hook 请求资源。我们首先使用 State/Reducer 和 Effect Hook 实现了请求资源。然后,我们了解了 axiosreact-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

观看以下视频,了解代码的实际应用:

http://bit.ly/2Mm9yoC

请注意,强烈建议您自己编写代码。不要简单地运行已提供的代码示例。重要的是你自己编写代码,以便能够正确学习和理解。但是,如果遇到任何问题,始终可以参考代码示例。

现在,让我们从本章开始。

创建多个页面

目前,我们的博客应用程序是一个所谓的单页应用程序。但是,大多数较大的应用程序都包含多个页面。在博客应用程序中,我们至少希望每篇博客文章都有一个单独的页面。

在设置路由之前,我们需要创建要显示的各种页面。在我们的博客应用程序中,我们将定义以下页面:

  • 主页,将显示所有文章的列表
  • 一篇文章页面,将显示单篇文章

所有页面都将显示一个 HeaderBar,它显示 HeaderUserBarChangeThemeCreatePost 组件。我们现在将首先为 HeaderBar 创建一个组件。之后,我们将实现页面组件。

创建 HeaderBar 组件

首先,我们将 App 组件的一些内容重构为 HeaderBar 组件。 HeaderBar 组件将包含我们希望在每个页面上显示的所有内容:HeaderUserBarChangeThemeCreatePost 组件。

让我们开始创建 HeaderBar 组件:

  1. 创建一个新文件夹:src/pages/
  2. 创建一个新文件 src/pages/HeaderBar.js,导入 React(使用 useContext Hook),并在那里定义组件。它将接受 setTheme 函数作为 prop:
import React, { useContext } from 'react'

export default function HeaderBar({ setTheme }) {
  return (
    <div>
    </div>
  )
}
  1. 现在,从 src/App.js 组件中剪切以下代码,并将其插入 HeaderBar 组件的 <div> 标签之间:
<Header text="React Hooks Blog" />
<ChangeTheme theme={theme} setTheme={setTheme} />
<React.Suspense fallback={"Loading..."}>
<UserBar />
</React.Suspense>
{ user && <CreatePost /> }
  1. 另外,从 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'
  1. 此外,导入 ThemeContexStateContext
import { ThemeContext, StateContext } from '../contexts'
  1. 然后,为 themestate 定义两个 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 (
  1. 现在,我们在 src/App.js 中导入 HeaderBar 组件:
import HeaderBar from './pages/HeaderBar'
  1. 最后,我们在 src/App.js 中渲染 HeaderBar 组件:
<div style={{ padding: 8 }}>
  <HeaderBar setTheme={setTheme} />
  <hr />

现在,我们有一个单独的 HeaderBar 组件,它将显示在所有页面上。接下来,我们继续创建 HomePage 组件。

创建 HomePage 组件

现在,我们将从 PostList 组件和与文章相关的 Resource Hook。同样,我们将重构 src/App.js,以便创建一个新组件。

让我们开始创建 HomePage 组件:

  1. 创建一个新文件 src/pages/HomePage.js,导入ReactuseEffectuseContext 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>
  )
}
  1. 然后,从 src/App.js 中剪切以下导入语句(并调整路径),并将它们添加到 src/pages/HomePage.js 中的 import React from 'react' 语句之后:
import { useResource } from 'react-request-hook'
import PostList from '../post/PostList'
  1. 接下来,从 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])
  1. 现在,从 src/App.js 中剪切以下渲染代码,并将其插入 src/pages/HomePage.js<div> 标签之间:
{error && <b>{error}</b>}
<PostList />
  1. 然后,在 src/App.js 中导入 HomePage 组件:
import HomePage from './pages/HomePage'
  1. 最后,在 <hr /> 标记下渲染 HomePage 组件:
<hr />
<HomePage />

现在,我们已经成功地将当前代码重构为 HomePage 组件。接下来,我们继续创建 PostPage 组件。

创建 PostPage 组件

我们现在将定义一个新的页面组件,其中我们只会从我们的 API 中获取单篇文章并显示它。

现在让我们开始创建 PostPage 组件:

  1. 创建一个新的 src/pages/PostPage.js 文件。
  2. 导入 ReactuseEffectuseResource Hook 以及 Post 组件:
import React, { useEffect } from 'react'
import { useResource } from 'react-request-hook' 
import Post from '../post/Post'
  1. 现在,定义 PostPage 组件,它将接受文章 id 作为prop:
export default function PostPage ({ id }) {
  1. 在这里,我们定义了一个 Resource Hook,它将获取相应的 post 对象。我们将 id 作为依赖项传递给 Effect Hook,以便在 id 更改时重新获取资源:
const [post, getPost] = useResource(() => ({
  url:  '/posts/${id}' ,
  method: 'get'
}))
useEffect(getPost, [id])
  1. 最后,我们渲染 Post 组件:
return (
 <div>
   {(post && post.data)
     ? <Post {...post.data} />
     : 'Loading...'
   }
   <hr />
 </div>
  )
}

我们现在还有一个单独的页面用于单篇文章。

测试 PostPage

为了测试新页面,我们将 src/App.js 中的 HomePage 组件替换为 PostPage 组件,如下所示:

  1. src/App.js 中导入 PostPage 组件:
import PostPage from './pages/PostPage'
  1. 现在,将 HomePage 组件替换为 PostPage 组件:
<PostPage id={'react-hooks'} />

正如我们所看到的,现在只有显示一篇文章,即“the React Hooks post”。

示例代码

示例代码可以在 Chapter07/chapter7_1 文件夹中找到。

只需运行 npm install 即可安装所有依赖项,运行 npm start 启动应用程序,然后在您的浏览器中访问 http://localhost:3000(如果它没有自动打开)。


(节选)

3

评论 (0)

取消