- 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 - 使用 React Hooks 进行状态管理
- ReactJS - 使用 React Hooks 进行组件生命周期管理
- ReactJS - 布局组件
- ReactJS - 分页
- ReactJS - Material UI
- ReactJS - Http 客户端编程
- ReactJS - 表单编程
- ReactJS - 受控组件
- ReactJS - 非受控组件
- ReactJS - Formik
- ReactJS - 条件渲染
- ReactJS - 列表
- ReactJS - Keys
- ReactJS - 路由
- ReactJS - Redux
- ReactJS - 动画
- ReactJS - Bootstrap
- ReactJS - 地图
- 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 - 端口
- ReactJS - 无 ES6 ECMAScript 的 React
- ReactJS - 无 JSX 的 React
- ReactJS - 调和
- ReactJS - Refs 和 DOM
- ReactJS - 渲染 Props
- ReactJS - 静态类型检查
- ReactJS - 严格模式
- ReactJS - Web Components
- 其他概念
- ReactJS - 日期选择器
- ReactJS - Helmet
- ReactJS - 内联样式
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - 走马灯
- ReactJS - 图标
- ReactJS - 表单组件
- ReactJS - 参考 API
- ReactJS 有用资源
- ReactJS - 快速指南
- ReactJS - 有用资源
- ReactJS - 讨论
ReactJS - 高阶组件
由于 React 组件通过组合(一个组件包含在另一个组件内部)而不是继承来进行互连,因此在一个 React 组件中使用的逻辑不会直接共享到另一个组件。React 社区提供了多种在组件之间共享逻辑的选项,其中一个选项就是高阶组件。HOC 本身并不是 React API,而是一种没有副作用的设计模式。
让我们在本节学习如何在 React 中使用高阶组件。
如何使用高阶组件
基本上,HOC 是一个函数,它接收一个 React 组件作为输入,然后基于输入组件创建一个新的 React 组件,并返回新创建的(包装的)组件。例如,HOC 函数可能接收一个纯数据渲染组件作为输入,然后返回一个新组件,该组件将具有数据获取功能和使用输入组件的数据渲染功能。
让我们看看如何使用 HOC 并逐步在两个组件之间共享逻辑。让我们考虑从外部 URL 获取和渲染数据的场景。
创建一个 HOC 函数,根据功能包含一个或多个输入参数。
HOC 函数的第一个参数应为具有次要逻辑的 React 组件(例如,数据渲染逻辑)。
应根据我们的需求定义 HOC 函数的第二个参数。对于我们的数据获取场景,数据 URL 是获取数据所需的必要信息。因此,我们应该将其作为 HOC 函数的第二个参数。
function createHOC(WrappedComponent, url) { // create new component using WrappedComponent }
如果确实必要,HOC 函数可以包含任意数量的参数。
在 HOC 函数内部创建一个新的组件,并在其 componentDidMount 事件中支持主要逻辑(例如,使用第二个 URL 参数进行数据获取逻辑)。
function createFetchHOC(WrappedComponent, url) { class DataFetcher extends React.Component { componentDidMount() { fetch(url) .then((response) => response.json()) .then((data) => { this.setState({ data: data }); }); } } }
通过传递从 componentDidMount 事件获取的数据来渲染输入组件。
function createFetchHOC(WrappedComponent, url) { class DataFetcher extends React.Component { render() { return ( <WrappedComponent data={this.state.data} {...this.props} /> ) } } }
返回新创建的组件。
function createFetchHOC(WrappedComponent, url) { class DataFetcher extends React.Component { } return DataFetcher; }
通过组合 DataFetcher (createFetchHOC) 和 Wrapped 组件创建一个新组件。
const UserListWithFetch = createFetchHOC( UserList, "users.json" );
最后,根据需要在任何地方使用新组件。
<UserListWithFetch />
应用 HOC 组件
让我们通过应用 HOC 组件创建一个新的应用程序。
首先,使用以下命令创建一个新的 React 应用程序并启动它。
create-react-app myapp cd myapp npm start
接下来,打开 App.css (src/App.css) 并删除所有 CSS 类。
// remove all css classes
接下来,创建一个新的 HOC 函数,如下所示:
import React from 'react'; function createFetchHOC(WrappedComponent, url) { class DataFetcher extends React.Component { constructor(props) { super(props); this.state = { data: [] }; } componentDidMount() { fetch(url) .then((response) => response.json()) .then((data) => { this.setState({ data: data }); }); } render() { return ( <WrappedComponent data={this.state.data} {...this.props} /> ) } } return DataFetcher; } export default createFetchHOC;
接下来,在 public 文件夹中创建一个名为 users.json (public/users.json) 的文件来存储用户信息。我们将尝试使用 FetchRenderProps 组件获取它并在我们的应用程序中显示它。
[{"id":1,"name":"Fowler","age":18}, {"id":2,"name":"Donnell","age":24}, {"id":3,"name":"Pall","age":26}]
接下来,在 public 文件夹中创建一个名为 todo_list.json (public/todo_list.json) 的文件来存储待办事项列表信息。我们将尝试使用 FetchRenderProps 组件获取它并在我们的应用程序中显示它。
[{"id":1,"title":"Learn JavaScript","is_done":true}, {"id":2,"title":"Learn React","is_done":true}, {"id":3,"title":"Learn Typescript","is_done":false}]
接下来,创建一个新的组件 UserList (src/Components/UserList.js) 来渲染用户,如下所示:
import React from "react"; class UserList extends React.Component { constructor(props) { super(props); } render() { return ( <> <ul> {this.props.data && this.props.data.length && this.props.data.map((item) => <li key={item.id}>{item.name}</li> )} </ul> </> ) } } export default UserList;
在这里,我们使用了 data props 来渲染用户列表。
接下来,创建一个新的组件 TodoList (src/Components/TodoList.js) 来渲染待办事项,如下所示:
import React from "react"; class TodoList extends React.Component { constructor(props) { super(props); this.todos = this.props.data } render() { return ( <> <ul> {this.props.data && this.props.data.length && this.props.data.map( (item) => <li key={item.id}>{item.title} {item.is_done && <strong>Done</strong>}</li> )} </ul> </> ) } } export default TodoList;
在这里,我们使用了 data props 来渲染待办事项列表。
接下来,创建一个新的组件 SimpleHOC 通过单个 HOC 组件渲染用户列表和待办事项列表。
import React from "react"; import UserList from "./UserList"; import TodoList from "./TodoList"; import createFetchHOC from "./createFetchHOC"; const UserListWithFetch = createFetchHOC( UserList, "users.json" ); const TodoListWithFetch = createFetchHOC( TodoList, "todo_list.json" ); class SimpleHOC extends React.Component { constructor(props) { super(props); } render() { return ( <> <UserListWithFetch /> <TodoListWithFetch /> </> ) } } export default SimpleHOC;
这里我们:
通过组合 TodoList 和 DataFetcher 组件创建了 UserListWithFetch 组件。
通过组合 Users 和 DataFetcher 组件创建了 TodoListWithFetch 组件。
接下来,打开 App.js 并使用 SimpleHOC 组件更新它。
import './App.css' import React from 'react'; import SimpleHOC from './Components/SimpleHOC' function App() { return ( <div className="container"> <div style={{ padding: "10px" }}> <div> <SimpleHOC /> </div> </div> </div> ); } export default App;
最后,在浏览器中打开应用程序并检查最终结果。应用程序将按如下所示渲染:
总结
高阶组件是共享组件之间逻辑的有效方法。它被广泛用于许多第三方组件,并且具有良好的成功率,并且是共享 React 领域逻辑的经过时间考验的方法。